C# Websocket 远程方在完成关闭握手之前关闭了 WebSocket 连接。

11

你好,我目前正在将websocket组件添加到我的基础网站中。我正在运行.NET Core 3.1 HTTP监听器来提供html服务,但是在实现websockets方面遇到了困难。

我之前使用过C#中的TCP协议并理解其中的所有流程,但是websockets对我来说是一件新事物。以下是接受websockets的C#代码:

        [Route("/socket", "GET")]
        public static async Task upgrade(HttpListenerContext c)
        {
            if (!c.Request.IsWebSocketRequest)
            {
                c.Response.StatusCode = 400;
                c.Response.Close();
                return;
            }

            try
            {
                var sock = (await c.AcceptWebSocketAsync(null)).WebSocket;
                byte[] buff = new byte[1024];
                var r = await sock.ReceiveAsync(buff, System.Threading.CancellationToken.None);
            }
            catch (Exception x) 
            {
                Console.WriteLine($"Got exception: {x}");
            }
           
            //WebSocketHandler.AddSocket(sock);
            
        }

我已经在这个函数中添加了var r = await sock.ReceiveAsync(buff, System.Threading.CancellationToken.None);,因为最初我在我的WebSocketHandler类中遇到了异常,所以我将代码移动到一个函数中进行测试。
以下是客户端:
  <script>
    let socket = new WebSocket("ws://localhost:3000/socket");

    socket.onopen = function (event) {
      console.log("[ OPENED ] - Opened Websocket!");
    };

    socket.onclose = function (event) {
      console.log("[ CLOSED ] - Socket closed");
    };

    socket.onerror = function (error) {
      console.log("[ ERROR ] - Got websocket error:");
      console.error(error);
    };
    socket.onmessage = function (event) {
      // This function will be responsible for handling events
      console.log("[ MESSAGE ] - Message received: ");
      const content = JSON.parse(event.data);
      console.log(content);
    };

  </script>

以下是客户端控制台的输出:

Navigated to http://127.0.0.1:5500/index.html
index.html:556 [ OPENED ] - Opened Websocket!
index.html:569 [ CLOSED ] - Socket closed

以下是来自C#服务器的异常信息:

Got exception: System.Net.WebSockets.WebSocketException (997): The remote party closed the WebSocket connection without completing the close handshake.
   at System.Net.WebSockets.WebSocketBase.WebSocketOperation.Process(Nullable`1 buffer, CancellationToken cancellationToken)
   at System.Net.WebSockets.WebSocketBase.ReceiveAsyncCore(ArraySegment`1 buffer, CancellationToken cancellationToken)
   at SwissbotCore.HTTP.Routes.UpgradeWebsocket.upgrade(HttpListenerContext c) in C:\Users\plynch\source\repos\SwissbotCore\SwissbotCore\HTTP\Routes\UpgradeWebsocket.cs:line 29

如果需要,我可以提供客户端发送的HTTP请求,但我完全被卡住了,非常感谢您的帮助。


传递给您的 onClose 函数的事件可能会包含一些信息。但很可能只是一个代码 1006。 - Peter Rasmussen
2个回答

2

你可能需要阅读RFC 6455第1.4节中的握手关闭RFC 6455第7.1.1节中的关闭WebSocket连接

基本上,在终止套接字之前,你需要让WebSocket端点知道你要关闭套接字。

对于你的服务器端,你应该捕获这个异常,因为在生产场景中发生网络问题时也可能会出现这种情况。


1
问题是,我并不想关闭套接字,它是自动关闭的。这就是我试图解决的问题。 - Quinch
https://azure.microsoft.com/pt-br/blog/introduction-to-websockets-on-windows-azure-web-sites/ - Svek

-2

我不确定为什么,但是如果你将try块内的代码更改为这样:

try
{
   var sock = (await c.AcceptWebSocketAsync(null)).WebSocket;
   byte[] buff = new byte[1024];
   
   await Listen(sock);
}
catch (Exception x) 
{
   Console.WriteLine($"Got exception: {x}");
}

private async Task Listen(WebSocket sock)
{
   return new Task(async () => 
   {
      while(sock.State == WebSocketState.Open)
      {
         var r = await sock.ReceiveAsync(buff, System.Threading.CancellationToken.None);
      }
   });
}

一切都会好起来的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接