.NET Core 基于Websocket的在线聊天室
Agile.Zhou 人气:0
## 什么是Websocket
我们在传统的客户端程序要实现实时双工通讯第一想到的技术就是socket通讯,但是在web体系是用不了socket通讯技术的,因为http被设计成无状态,每次跟服务器通讯完成后就会断开连接。
在没有websocket之前web系统如果要做双工通讯往往使用http long polling技术。http long polling 每次往服务器发送请求后,服务端不会立刻返回信息来结束请求,而是一直挂着直到有数据需要返回,或者等待超时了才会返回。客户端在结束上一次请求后立刻再发送一次请求,如此反复。http long polling虽然能实现web系统的双工通讯,但是有个很大的问题,就是基于http协议客户端每次发送请求都需要携带巨大的头部。在并发交互少量数据的时候非常不划算,对服务器资源的消耗也是巨大的。
websocket很好的改善了以上问题。它基于tcp重新设计了一套协议,同时又兼容http,默认跟http一样使用80/443端口。websocket链接建立本质上就是一次http请求,直接使用http协议的upgrade头来标识这是一次websocket请求,服务端回复101状态码表示“握手”成功。
```
//客户端请求
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
//服务端响应
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Location: ws://example.com/
```
## 使用asp.net core来处理websocket
上面我们简单的了解了websocket,那么如何来使用asp.net core处理websocket呢?因为websocket的握手就是一次http请求,那么我们就可以使用一个middleware来拦截websocket的请求,把建立的链接统一进行管理,其实微软已经帮我们简单的封装过了。
### 新建一个asp.net core网站
![](https://images.cnblogs.com/cnblogs_com/kklldog/1401672/o_200304033211TIM%E6%88%AA%E5%9B%BE20200304105929.jpg)
### 新建WebsocketHandlerMiddleware中间件
这个中间件就是我们管理websocket链接的入口,我们调用context.WebSockets.AcceptWebSocketAsync()方法把请求转换为websocket链接。
#### 在Invoke方法内接收websocket链接
```
public async Task Invoke(HttpContext context)
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
string clientId = Guid.NewGuid().ToString(); ;
var wsClient = new WebsocketClient
{
Id = clientId,
WebSocket = webSocket
};
try
{
await Handle(wsClient);
}
catch (Exception ex)
{
_logger.LogError(ex, "Echo websocket client {0} err .", clientId);
await context.Response.WriteAsync("closed");
}
}
else
{
context.Response.StatusCode = 404;
}
}
else
{
await _next(context);
}
}
```
#### 在Hanle方法等待客户端的消息
```
private async Task Handle(WebsocketClient webSocket)
{
WebsocketClientCollection.Add(webSocket);
_logger.LogInformation($"Websocket client added.");
WebSocketReceiveResult result = null;
do
{
var buffer = new byte[1024 * 1];
result = await webSocket.WebSocket.ReceiveAsync(new ArraySegment
加载全部内容