Socket,長連接,消息推送,消息提醒,未讀消息提醒,消息通知,未讀消息通知


今天公司要搞個類似QQ空間的未讀消息通知,於是想到用WebSocket長連接,搜索一些資料后,調試好久,還以為不行,結果發現是IIS版本的原因,我本地用的Win7的系統,是IIS6的,本地測試一直不行,后來查資料發現用這個WebSocket要IIS8,我直接放服務器上,測試就OK了,廢話不多說,直接上代碼。我用的MVC+EF的框架。

1、新建一個Controller,繼承APIController

[Description("消息")]
public class MessageController : ApiController
{

//注入消息通知的業務邏輯
public readonly NoticeService NoticeService = new NoticeService();


[AcceptVerbs("post", "get")]
[Description("長連接線程檢測")]
public HttpResponseMessage ProcessRequest()
{
if (HttpContext.Current.IsWebSocketRequest)
{
HttpContext.Current.AcceptWebSocketRequest(ProcessChat);
return new HttpResponseMessage(HttpStatusCode.SwitchingProtocols);
}
else
{
return new HttpResponseMessage(HttpStatusCode.SwitchingProtocols);
}

}

//發送信息回客戶端
private async Task ProcessChat(AspNetWebSocketContext context)
{

WebSocket socket = context.WebSocket;
while (true)
{
if (socket.State == WebSocketState.Open)
{
ArraySegment<byte> buffer = new ArraySegment<byte>(new byte[2048]);
WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None);

//約定好客戶端只傳用戶ID過來
string userId = Encoding.UTF8.GetString(buffer.Array, 0, result.Count);

var operateUserId = Convert.ToInt32(userId);
//默認沒有
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes("false"));
for (int i = 0; i < 100; i++)
{

//我這默認30秒查詢一次數據庫,判斷是否有未讀消息然后提示客戶端,大家對這有什么好的建議嗎?請交流一下好的idea,我想的是這循環100次,100*30秒也有50分鍾了,基本還是夠用了,正常情況也沒有誰50分鍾一直在線操作的吧。很LOW的想法,請大家給我good idea,我要改進,我覺得這樣處理很low,但是短時間又沒好的想法
Thread.Sleep(30000);

//查詢數據庫是否有這個userid的未讀消息,Type=2是未讀消息
var messages = await
NoticeService.MessageInfos()
.CountAsync(p => p.OwerId == userId && p.Type == 2);
buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(messages.ToString()));

//返回未讀消息的個數為messages==0沒有未讀消息,messages>0有未讀消息
await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
}
await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);

}
else
{
break;
}
}
}


}

以上就是服務器端的代碼,下面開始客戶端的代碼

2、客戶端怎么發起長連接喃?請往下看

<html>

<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
@*<script src="jquery-2.0.3.min.js"></script>*@
<script src="~/Content/Js/jquery/jquery.min.js" type="text/javascript"></script>
<script>
var ws;
$().ready(function ()
{
$('#conn').click(function ()
{

//替換下面的IP地址和端口號
ws = new WebSocket('ws://' + '你的服務器代碼所在的IP地址' + ':' + '端口號' + '/API/Message/ProcessRequest');

$('#tips').text('正在連接');
ws.onopen = function ()
{
$('#tips').text('已經連接');
}
ws.onmessage = function (evt)
{
$('#tips').text(evt.data);
}
ws.onerror = function (evt)
{
$('#tips').text(JSON.stringify(evt));
}
ws.onclose = function ()
{
$('#tips').text('已經關閉');
}
});

$('#close').click(function ()
{
ws.close();
});

$('#send').click(function ()
{
if (ws.readyState == WebSocket.OPEN) {
ws.send($('#content').val());
}
else {
$('#tips').text('連接已經關閉');
}
});

});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>

<input id="conn" type="button" value="連接" />
<input id="close" type="button" value="關閉" />
<span id="tips"></span>
<input id="content" type="text" />
<input id="send" type="button" value="發送" />
</div>
</form>
</body>

</html>

3、開始測試

點擊連接,輸入框輸入ID,測試OK,完事

我這默認30秒查詢一次數據庫,判斷是否有未讀消息然后提示客戶端,大家對這有什么好的建議嗎?請交流一下好的idea


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM