目录
WebSocket原理
支持的客户端
ASP.NET实现
服务端
客户端
踩到的坑
有时我们需要由浏览器实时接收消息或者数据,这样的需求使用传统的Ajax轮询浪费资源不说效率还十分低下。而WebSocket技术可以帮助我们轻松解决这些问题。
WebSocket原理
由客户端发起,向服务器发送websocket握手信号,受支持的服务端随即向客户端回应并保持此连接不会自动断开。之后的事情就很简单了,我们可以从服务端或浏览器端任何一方主动发送数据,而另一方就能即时接收到。
实质即:客户端与服务器之间建立的TCP长连接。
支持的客户端
浏览器 | 支持情况 |
---|
Chrome | Chrome version 4+支持 | Firefox | Firefox version 5+支持 | IE | IE version 10+支持 | Safari | IOS 5+支持 | Android Brower | Android 4.5+支持 |
上表来自于这里(这位兄台似乎也是转载的别人)
- 支持WebSocket的最低IIS版本为7.0,6.x版本及以下是不支持的,不能正确处理握手并建立连接。
- 最新的Jexus服务器已经支持WebSocket
ASP.NET实现
服务端
本人习惯使用VB.NET,实在想看C#的就麻烦您自己转码一下吧!
在新建的MVC控制器类中添加如下方法 - Sub GetSocket()
- If HttpContext.IsWebSocketRequest Then
- HttpContext.AcceptWebSocketRequest(AddressOf WebSocketResponser)
- End If
- End Sub
复制代码- Async Function WebSocketResponser(context As AspNetWebSocketContext) As Tasks.Task
- Try
- Dim soc = context.WebSocket
- Dim buff = WebSocket.CreateClientBuffer(256, 256)
- Do
- '接收数据到缓冲区。此操作将悬停等待,直到接收到数据或连接超时。
- Dim retr = Await soc.ReceiveAsync(buff, CancellationToken.None)
- Dim ass As New ArraySegment(Of Byte)(buff.Array, 0, retr.Count)
- '发送数据到客户端
- Await soc.SendAsync(ass, WebSocketMessageType.Text, True, CancellationToken.None)
- Debug.Print("已发送")
- Loop
- Catch ex As Exception
- Debug.Print(ex.Message)
- End Try
- End Function
复制代码
上面的方法为接收WebSocket握手请求的操作方法。操作方法接收请求之后,判断是否为有效WebSocket请求,若是则接受并建立连接,然后执行传入的委托函数,在这个委托函数中你可以对新建的WebSocket连接进行发送、接收等操作。
客户端
客户端就简单得多了,在受支持的浏览器中创建WebSocket实例并绑定事件即可。 - <a class="btn btn-default" onclick="testSocket();">
- 测试按钮
- </a>
- <script>
- //自己创建的工程,这里根据自己的项目进行修改。比如新建的网站,端口号就会和这里的代码不一样
- var ws = new WebSocket("ws://localhost:64079/Home/GetSocket");//这段代码执行后将会立即发送握手请求
- //ws.binaryType="blob"; 设定接收到的二进制数据当作blob对待
- //ws.binaryType="arraybuffer"; 设定接收到的二进制数据当作ArrayBuffer对待
- //建立连接成功后会触发
- ws.onopen = function (e) {
- console.log("已连接");
- }
- //收到消息后触发
- ws.onmessage = function (msg) {
- try {
- //接收到的数据内容在msg的data属性中
- var dat = msg.data;
- alert(dat);
- } catch (e) {
- alert(JSON.stringify(e));
- }
- }
- //发生错误后触发
- ws.onerror = function (err) {
- alert(JSON.stringify(err));
- }
- //连接关闭后触发,此时ws这个实例也就废了,想要使用需要new一个新的。
- ws.onclose = function (e) {
- console.log("已断开。" + JSON.stringify(e));
- }
- function testSocket() {
-
- ws.send("测试内容");
- }
-
- </script>
复制代码
- 发送的数据若是字符串,则会接收到字符串。字符串会经过UTF-8编码,非字符以字符串方式无法发送,会报错并可能导致连接关闭。
- 发送的数据为二进制时,若设置了binaryType属性,则会据此返回对应的数据类型;若未设置,默认为arraybuffer。
踩到的坑
-
发送数据过大时,需要分片发送,单片不能超过64K。这是我在官方公布源码当作看到的,感兴趣的话可以自己找找 -
不要想当然的以为执行完了就什么都不用管了,MVC控制器会在所有操作执行完毕后销毁线程释放资源,你的WebSocket连接也就跟着一块没了。我的办法是死循环读数据(可能还要再改一下服务器连接超时时间,没记错的话默认是半个小时,超过这个时间有心跳包也不管用) -
WebSocket超过90秒没有数据交互就会被服务器判断为非活跃连接,并可能将连接关闭。解决办法是心跳包,例如每隔30秒发送一个数据包,再由对方回复。 -
以上代码在IIS Express 10.0 / Vivaldi 3.1.1929.45 (Stable channel) (64 位)中测试成功。
代码文件点此下载 来源:https://blog.csdn.net/u011587852/article/details/89788465 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |