博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET Web API上实现 Web Socket
阅读量:5240 次
发布时间:2019-06-14

本文共 3904 字,大约阅读时间需要 13 分钟。

 

1. 什么是Web Socket

Web Socket是Html5中引入的通信机制,它为浏览器与后台服务器之间提供了基于TCP的全双工的通信通道。用以替代以往的LongPooling等comet style的实时解决方案。基于它们之间的比较以及Web Socket的优势参考.

2. Web Socket如何工作

Connect

Web Socket在建立之前需要先与后台服务器进行握手。具体来说通过如下Http请求:

GET /chat HTTP/1.1Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com

后台服务器如果支持切换到WebSocket,会返回如下Response:

HTTP/1.1 101 Switching ProtocolsUpgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat

浏览器收到该Response会切换到基于当前TCP连接的WebSocket通道。

Data Transfer

连接建立后,浏览器端可以和服务器发送Text类型的消息进行全双工的通信,类似于基于TCP的Socket通信。

Disconnect

当浏览器或者后台服务器想终止通信,需向对方发送类型为Close的消息,并等待对方收到消息并确认后连接断开。

3. 浏览器,服务器支持情况

参考维基百科,目前浏览器的支持情况如下:

IE Chrome Firefox Safari Opera    
10+ 16+ 11+ 6+ 12.10+    

 

 

 

IIS从8.0开始支持Web Socket

好了,很长的铺垫之后正式进入Coding:

1. 为了接受浏览器端的握手请求,我们需要定义一个Web Api接口接受握手请求

[RoutePrefix("api/chat")]    public class ChatController : ApiController    {        private static List
_sockets = new List
(); [Route] [HttpGet] public HttpResponseMessage Connect(string nickName) { HttpContext.Current.AcceptWebSocketRequest(ProcessRequest); //在服务器端接受Web Socket请求,传入的函数作为Web Socket的处理函数,待Web Socket建立后该函数会被调用,在该函数中可以对Web Socket进行消息收发 return Request.CreateResponse(HttpStatusCode.SwitchingProtocols); //构造同意切换至Web Socket的Response. } }

2. 为了对Web Socket进行消息收发,需要定义Web Socket的消息收发函数(以前的.net 版本是接受一个实现特定接口的对象,新版改成了接受一个函数,总觉得怪怪的),代码如下:

public async Task ProcessRequest(AspNetWebSocketContext context)      {            var socket = context.WebSocket;//传入的context中有当前的web socket对象            _sockets.Add(socket);//此处将web socket对象加入一个静态列表中        //进入一个无限循环,当web socket close是循环结束            while (true)            {                var buffer = new ArraySegment
(new byte[1024]); var receivedResult = await socket.ReceiveAsync(buffer, CancellationToken.None);//对web socket进行异步接收数据 if (receivedResult.MessageType == WebSocketMessageType.Close) { await socket.CloseAsync(WebSocketCloseStatus.Empty, string.Empty, CancellationToken.None);//如果client发起close请求,对client进行ack _sockets.Remove(socket); break; } if (socket.State == System.Net.WebSockets.WebSocketState.Open) { string recvMsg = Encoding.UTF8.GetString(buffer.Array, 0, receivedResult.Count); var recvBytes = Encoding.UTF8.GetBytes(recvMsg); var sendBuffer = new ArraySegment
(recvBytes); foreach (var innerSocket in _sockets)//当接收到文本消息时,对当前服务器上所有web socket连接进行广播 { if (innerSocket != socket) { await innerSocket.SendAsync(sendBuffer, WebSocketMessageType.Text, true, CancellationToken.None); } } } }

服务器端代码就绪,浏览器端如何去调用呢,继续看代码:

var webSocket = new WebSocket("ws://localhost/api/chat?nickName=" + nickName.value);    webSocket.onopen = function () {        console.log("opened");    }    webSocket.onerror = function () {        console.log("web socket error");    }    webSocket.onmessage = function (event) {
    console.log("web socket error");
} self.webSocket.onclose = function () { console.log("closed"); }

这样就建立了一个web socket连接并能收到消息了,当然也会有发送消息的接口:

webSocket.send(“Hello Web Socket”);

到这里,基于web socket的全双工通信机制已经建立好了。文中的demo是一个简易的聊天室程序。代码链接:

补充:

HttpContext的AcceptWebSocketRequest方法只能接受一个函数确实有点不方便,也不利于封装与复用。因此为其添加了一个接受对象的重载extension方法,然后定义一个类WebSocketHandler来处理消息的收发和连接的关闭。详见上面的代码链接。

转载于:https://www.cnblogs.com/zxtceq/p/9066553.html

你可能感兴趣的文章
Kth Smallest Element in Unsorted Array
查看>>
vue项目中使用百度统计
查看>>
第 十一 次作业
查看>>
利用PHP SOAP实现WEB SERVICE[转载]
查看>>
[leetcode DP]120. Triangle
查看>>
数组filter()参数详解,巧用filter()数组去重
查看>>
查询项目中未被使用的js、css和图片
查看>>
Cookie.js
查看>>
Django Blog学习笔记(一)
查看>>
什么是“堆”,"栈","堆栈","队列",它们的区别
查看>>
什么是lambda函数?它有什么好处?
查看>>
在线的IDE(Ideone)支持Java/Python/Go/D
查看>>
第4次作业
查看>>
hash 哈希
查看>>
淘宝的技术博客
查看>>
Linux commands
查看>>
JVM ,Java paper
查看>>
https://www.callicoder.com/java-8-completablefuture-tutorial/
查看>>
YARN Resource Management
查看>>
作业5:需求分析
查看>>