记一下在IIS中部署WebSocket服务的经验

发布时间 2023-12-26 15:23:31作者: 遇到困难睡大觉~zZ

因业务需求需要使用长连接推送数据,这边选择使用.NET框架原生支持的WebSocket技术。

 

一、版本要求

  1.  对于IIS的版本必须是 IIS 8.0 及以上
  2.  .NET Framework版本必须为 4.5 及以上

PS:低于上述版本,需要自己实现协议或寻找第三方实现

 

二、IIS配置

  1. 在服务器IIS上安装“WebSocket 协议”服务,参考微软官方教程
  2. 在Web站点中的站点配置里启用Websocket支持,参考教程
    1. 选择一个站点或应用程序
    2. 找到配置编辑器
    3. 选择节点system.webServer/webSocket
    4. 设置enabledtrue

 

三、测试代码

参考于《WebSocket在Asp.Net中的例子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.WebSockets;

namespace SimpleWebSocket
{
    /// <summary>
    /// 
    /// </summary>
    public class WebSocketHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            //检查 查询是否是WebSocket请求
            if (HttpContext.Current.IsWebSocketRequest)  
            {
                //如果是,我们附加异步处理程序
                context.AcceptWebSocketRequest(WebSocketRequestHandler);
            }
        }

        public bool IsReusable { get { return false; } }

        //异步请求处理程序
        public async Task WebSocketRequestHandler(AspNetWebSocketContext webSocketContext)
        {
            //获取当前的WebSocket对象
            WebSocket webSocket = webSocketContext.WebSocket;

            /*
             * 我们定义一个常数,它将表示接收到的数据的大小。 它是由我们建立的,我们可以设定任何值。 我们知道在这种情况下,发送的数据的大小非常小。
            */
            const int maxMessageSize = 1024;

            //received bits的缓冲区
            var receivedDataBuffer = new ArraySegment<Byte>(new Byte[maxMessageSize]);

            var cancellationToken = new CancellationToken();

            //检查WebSocket状态
            while (webSocket.State == WebSocketState.Open)
            {
                //读取数据 
                WebSocketReceiveResult webSocketReceiveResult = await webSocket.ReceiveAsync(receivedDataBuffer, cancellationToken);

                //如果输入帧为取消帧,发送close命令
                if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close)
                {
                    await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, String.Empty, cancellationToken);
                }
                else
                {
                        byte[] payloadData = receivedDataBuffer.Array.Where(b => b != 0).ToArray();

                        //因为我们知道这是一个字符串,我们转换它
                        string receiveString = System.Text.Encoding.UTF8.GetString(payloadData, 0, payloadData.Length);

                        //将字符串转换为字节数组. 
                        var newString = String.Format("Hello, " + receiveString + " ! Time {0}", DateTime.Now.ToString());
                        Byte[] bytes = System.Text.Encoding.UTF8.GetBytes(newString);

                        //发回数据
                        await webSocket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, cancellationToken);
                }

            }
        }
    }

}

 

四、项目配置

在项目的Web.config文件里确保如下配置正确:

<configuration>
  <system.web>
    <httpRuntime targetFramework="4.5" />
  </system.web>
</configuration>

主要是“<httpRuntime targetFramework="4.5" />”这行配置,一定要4.5及以上版本。

PS:如果有 httpRuntime 这个节点了,则加上 targetFramework="4.5" 即可

然后将项目部署到IIS上

 

其他问题

一、配置都没问题,本地测试也没问题,但线上WebSocket就是连不上,且无任何报错,仿佛被什么拦截了

检查一下IIS里部署的目标站点其开放的端口,是否只开放了443端口,即https。此时用wss协议连接试试,如“wss://127.0.0.1/test.ashx”

PS:因为网站出于安全考虑,一般不使用未加密的http协议,即80端口。而ws协议连接的正是80端口,就被拦截了。使用wss协议会连接443端口,就正常了。