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

今天公司要搞個相似QQ空間的未讀消息通知,因而想到用WebSocket長鏈接,搜索一些資料後,調試很久,還覺得不行,結果發現是IIS版本的緣由,我本地用的Win7的系統,是IIS6的,本地測試一直不行,後來查資料發現用這個WebSocket要IIS8,我直接放服務器上,測試就OK了,廢話很少說,直接上代碼。我用的MVC+EF的框架。javascript

一、新建一個Controller,繼承APIControllerhtml

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

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


[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);socket

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

//我這默認30秒查詢一次數據庫,判斷是否有未讀消息而後提示客戶端,你們對這有什麼好的建議嗎?請交流一下好的idea,我想的是這循環100次,100*30秒也有50分鐘了,基本仍是夠用了,正常狀況也沒有誰50分鐘一直在線操做的吧。很LOW的想法,請你們給我good idea,我要改進,我以爲這樣處理很low,可是短期又沒好的想法
Thread.Sleep(30000);ide

//查詢數據庫是否有這個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;
}
}
}


}

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

二、客戶端怎麼發起長鏈接喃?請往下看

<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>

三、開始測試

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

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

相關文章
相關標籤/搜索