AspNet 接入WebSocket
文章目录
- [AspNet 接入WebSocket](#AspNet 接入WebSocket)
- 前言
- 一、Http场景
- 二、WebScoket场景
- 三、图解
- [四、在Asp.net Web应用如何接入WebSocket](#四、在Asp.net Web应用如何接入WebSocket)
-
- 1.WebsocketHelper
- [2. Controller](#2. Controller)
- 总结
前言
提示:WebScoket相信大家都不陌生
WebScoket
是与Http协议类似的一种协议,区别在于WebSocket
属于服务端和客户端双向通信而Http是无状态式,每次请求都服务端都不清楚客户端是谁,所以Http需要Cookie
,Session
来实现识别客户端信息的作用。
提示:以下是本篇文章正文内容,下面案例可供参考
一、Http场景
在普通的Web
应用下一般多用于Http实现与服务端通信,由于Http是无状态的在并发、性能方面也相对较好
二、WebScoket场景
WebScoket
为了实现一些特殊场景,比如:即时通讯、消息推送等对数据响应速度较快的情况而应对,当然由于这种协议属于双向通信也是一种长时间保持连接的状态,对资源消耗、性能提高、并发量的支持不是很高。
三、图解
四、在Asp.net Web应用如何接入WebSocket
1.WebsocketHelper
代码如下(示例):
csharp
public static class WebsocketHelper
{
/// <summary>
/// 记录客户端连接
/// </summary>
public static ConcurrentDictionary<string, WebSocket> webSockets = new ConcurrentDictionary<string, WebSocket>();
//private static List<Authority_User> UserList = new QMS_BaseResource().Authority_User.AsNoTracking().Where(p => p.UserType!=null && (p.UserType == 4 || p.UserType == 0)).ToList();
/// <summary>
/// 接受信息
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async static Task ProcessRequest(AspNetWebSocketContext context)
{
try
{
//获取路由
string route = context.RawUrl;
//if (route.Contains("?"))
//{
// route = route.Split('?')[0];
//}
string key = context.UserHostAddress + route;
//传入的context中有当前的websocket对象
var socket = context.WebSocket;
//此处将web socket对象加入一个静态字典中.
if (!webSockets.ContainsKey(key))
{
//将IP地址和路由设置为hashTable的key值,若hashTable中存在该IP地址则不再添加
QMS.PMC.LogNet.Log4NetHelper.Info($"{key}连接成功");
webSockets.TryAdd(key, socket);
}
//进入一个无限循环,当websocket close时循环结束
while (true)
{
//关闭连接
var buffer = new ArraySegment<byte>(new byte[1024]);
//对web socket进行异步接收数据
var receivedResult = await socket.ReceiveAsync(buffer, CancellationToken.None);
int count = receivedResult.Count;
if (receivedResult.MessageType == WebSocketMessageType.Close)
{
//如果client发起close请求,对client进行ack
await socket.CloseAsync(WebSocketCloseStatus.Empty, string.Empty, CancellationToken.None);
QMS.PMC.LogNet.Log4NetHelper.Info($"{key}断开连接");
WebSocket outsocket;
if (webSockets.TryRemove(key, out outsocket))
{
break;
}
}
while (receivedResult != null && !receivedResult.CloseStatus.HasValue)
{
if (count > buffer.Count)
{
throw new Exception("receive WebSocket data error");
}
else if (count == buffer.Array.Count(n=>n!=0))
{
break;
}
}
// 判断计划员更新数据后,服务端通知对应的班组长(客户端), 如果班组长客户端未登陆, 等待登陆时再抓取当天未读消息
// 服务端》客户端 = 班组长角色
// string messagebody = Encoding.UTF8.GetString(buffer.Array);
}
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 将数据发送给所有已连接的客户端
/// </summary>
/// <param name="data"></param>
/// <param name="route">接口路由</param>
public static void SendAll(string data, string route)
{
var recvBytes = Encoding.UTF8.GetBytes(data);
var sendBuffer = new ArraySegment<byte>(recvBytes);
if (webSockets.Any())
{
var webs = webSockets.Where(w => w.Key.Contains(route)).ToList();
if (webs != null)
{
foreach (var item in webs)
{
item.Value.SendAsync(sendBuffer, WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}
}
}
2. Controller
通过HTTP
做一个代理建立WebScoket握手连接
csharp
[HttpGet]
public HttpResponseMessage GetConnect(string uid)
{
//在服务器端接受WebSocket请求
HttpContext.Current.AcceptWebSocketRequest(WebsocketHelper.ProcessRequest);
//Response.
return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);
}
总结
小ps:
虽然Web
应用可以接入WebScoket
,但是这种对应用的并发、性能方面的支持不太好,对于大体量的Web
服务还是需要搭建一个独立的WebSocket
应用。
参考文献
阮一峰