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

posted @ 2016-11-17 12:17  我就是老王  阅读(4609)  评论(0编辑  收藏  举报