ASP.NET MVC 实现WebSocket

目录

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控制器类中添加如下方法

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 位)中测试成功。 

代码文件点此下载

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值