找回密码
 会员注册
查看: 158|回复: 0

ASP.NET MVC 实现WebSocket

[复制链接]

1389

主题

5

回帖

496万

积分

管理员

积分
4962990
发表于 2024-2-29 08:40:34 | 显示全部楼层 |阅读模式

目录

WebSocket原理

支持的客户端

ASP.NET实现

服务端

客户端

 踩到的坑


有时我们需要由浏览器实时接收消息或者数据,这样的需求使用传统的Ajax轮询浪费资源不说效率还十分低下。而WebSocket技术可以帮助我们轻松解决这些问题。 

WebSocket原理

由客户端发起,向服务器发送websocket握手信号,受支持的服务端随即向客户端回应并保持此连接不会自动断开。之后的事情就很简单了,我们可以从服务端或浏览器端任何一方主动发送数据,而另一方就能即时接收到。

实质即:客户端与服务器之间建立的TCP长连接。

支持的客户端

 

浏览器支持情况
ChromeChrome version 4+支持
FirefoxFirefox version 5+支持
IEIE version 10+支持
SafariIOS 5+支持
Android BrowerAndroid 4.5+支持

上表来自于这里(这位兄台似乎也是转载的别人)

  • 支持WebSocket的最低IIS版本为7.0,6.x版本及以下是不支持的,不能正确处理握手并建立连接。 
  • 最新的Jexus服务器已经支持WebSocket

ASP.NET实现

服务端

本人习惯使用VB.NET,实在想看C#的就麻烦您自己转码一下吧!

 在新建的MVC控制器类中添加如下方法

  1. Sub GetSocket()
  2. If HttpContext.IsWebSocketRequest Then
  3. HttpContext.AcceptWebSocketRequest(AddressOf WebSocketResponser)
  4. End If
  5. End Sub
复制代码
  1. Async Function WebSocketResponser(context As AspNetWebSocketContext) As Tasks.Task
  2. Try
  3. Dim soc = context.WebSocket
  4. Dim buff = WebSocket.CreateClientBuffer(256, 256)
  5. Do
  6. '接收数据到缓冲区。此操作将悬停等待,直到接收到数据或连接超时。
  7. Dim retr = Await soc.ReceiveAsync(buff, CancellationToken.None)
  8. Dim ass As New ArraySegment(Of Byte)(buff.Array, 0, retr.Count)
  9. '发送数据到客户端
  10. Await soc.SendAsync(ass, WebSocketMessageType.Text, True, CancellationToken.None)
  11. Debug.Print("已发送")
  12. Loop
  13. Catch ex As Exception
  14. Debug.Print(ex.Message)
  15. End Try
  16. End Function
复制代码

 上面的方法为接收WebSocket握手请求的操作方法。操作方法接收请求之后,判断是否为有效WebSocket请求,若是则接受并建立连接,然后执行传入的委托函数,在这个委托函数中你可以对新建的WebSocket连接进行发送、接收等操作。

客户端

客户端就简单得多了,在受支持的浏览器中创建WebSocket实例并绑定事件即可。

  1. <a class="btn btn-default" onclick="testSocket();">
  2. 测试按钮
  3. </a>
  4. <script>
  5. //自己创建的工程,这里根据自己的项目进行修改。比如新建的网站,端口号就会和这里的代码不一样
  6. var ws = new WebSocket("ws://localhost:64079/Home/GetSocket");//这段代码执行后将会立即发送握手请求
  7. //ws.binaryType="blob"; 设定接收到的二进制数据当作blob对待
  8. //ws.binaryType="arraybuffer"; 设定接收到的二进制数据当作ArrayBuffer对待
  9. //建立连接成功后会触发
  10. ws.onopen = function (e) {
  11. console.log("已连接");
  12. }
  13. //收到消息后触发
  14. ws.onmessage = function (msg) {
  15. try {
  16. //接收到的数据内容在msg的data属性中
  17. var dat = msg.data;
  18. alert(dat);
  19. } catch (e) {
  20. alert(JSON.stringify(e));
  21. }
  22. }
  23. //发生错误后触发
  24. ws.onerror = function (err) {
  25. alert(JSON.stringify(err));
  26. }
  27. //连接关闭后触发,此时ws这个实例也就废了,想要使用需要new一个新的。
  28. ws.onclose = function (e) {
  29. console.log("已断开。" + JSON.stringify(e));
  30. }
  31. function testSocket() {
  32. ws.send("测试内容");
  33. }
  34. </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
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-26 12:21 , Processed in 0.742548 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表