【问题标题】:Connection to socket gets error "WebSocket opening handshake timed out" using Javascript and C#使用 Javascript 和 C# 连接到套接字时出现错误“WebSocket 打开握手超时”
【发布时间】:2020-09-03 16:28:50
【问题描述】:

大约 4 小时的研究……我们开始吧。

我有一个 C# 程序,它发送和侦听来自特定 Socket 的任何内容。使用套接字,C# 可以向它发送东西,也可以从它那里接收。现在,转到我的 JavaScript 文件,我正在使用 WebSocket 接口与 C# 通信,但不起作用(通常在几分钟后超时)。当 Socket 在线时,JavaScript 代码最多需要大约 4 分钟,然后抛出一个错误,说“WebSocket 打开握手超时”。问题是我知道它可以找到,因为当 ip 的端口不存在时,JavaScript 文件会在接下来的几秒钟内引发错误。

我做过的事情:

关闭所有防火墙,ip和端口开头同时使用ws和wss(例如:wss://xxx.xxx.x.xx:11111),更改端口,更改ip为有效ip仍然可以到达,研究 4 小时。

C#:

IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = IPAddress.Parse("ip");
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, 11111);

Socket listener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

try
{
    listener.Bind(localEndPoint);

    listener.Listen(10);

    while (true)
    {

        Console.WriteLine("Waiting connection...");

        Socket clientSocket = listener.Accept();

        byte[] bytes = new Byte[1024];
        string data = null;

        while (true)
        {

            int numByte = clientSocket.Receive(bytes);

            data += Encoding.ASCII.GetString(bytes, 0, numByte);

            if (data.IndexOf("<EOF>") > -1)
            {
                break;
            }
        }

        Console.WriteLine("Text received -> {0} ", data);
        byte[] message = Encoding.ASCII.GetBytes("Test Server");

        clientSocket.Send(message);

        clientSocket.Shutdown(SocketShutdown.Both);
        clientSocket.Close();
    }
}
catch (Exception e)
{
    Console.WriteLine(e.ToString());
}

JavaScript:

socket = new WebSocket("wss://ip:11111");
socket.onopen = function()
{
    alert("Connected!");
}
socket.onerror = function()
{
    alert("Connection Failed");
}

ip是本地的

长话短说,C# 可以与自己通信,而 JavaScript 可以找到它但无法与之通信。

【问题讨论】:

  • 好的,但正如我所说,我使用过 ws。另外,我不知道如何获得Connection: Upgrade GET ws://websocket.example.com/ HTTP/1.1 Origin: http://example.comConnection: Upgrade Connection: Upgrade Host: websocket.example.comConnection: Upgrade Upgrade: websocket
  • 我毫不怀疑 WS 已与正确实现握手/接受传入 WS 请求的服务器一起使用。上面的代码没有 - 因为它没有遵守定义的协议 - 并且预计不会工作。
  • 我强烈建议使用System.Net.HttpListener,它可以通过HttpListenerContext / HttpListenerRequest 为您建立System.Net.Websocket 连接。
  • 好的。我现在就解决这个问题。等我弄清楚了,我会尽快回来的。
  • 其实this answer告诉你如何使用HttpListener进行设置。

标签: javascript c# html sockets websocket


【解决方案1】:

正确地完成一次握手。 (或者使用一个库/连接类型。)

WebSocket 协议(如 RFC6455 - The WebSocket Protocol 中的原始定义)打开一个普通的不受限制的套接字,部分是出于安全原因。

由于握手未完成,客户端 WS 请求将超时,因为从未收到 HTTP“升级”响应。 在握手完成之前,WS 不会在底层 TCP 连接上处于活动状态。

发起 WebSocket 连接(“握手”)在 RFC 的 section 4 中定义。 How JavaScript works: Deep dive into WebSockets and HTTP/2 with SSE + how to pick the right path也有讨论。

客户端通过称为 WebSocket 握手的过程建立 WebSocket 连接。此过程从客户端向服务器发送常规 HTTP 请求开始。此请求中包含一个 Upgrade 标头,通知服务器客户端希望建立 WebSocket 连接。

..

现在[在]握手完成后,初始 HTTP 连接被替换为 WebSocket 连接,该连接使用相同的底层 TCP/IP 连接。此时,任何一方都可以开始发送数据了。

【讨论】:

  • 我不知道GET ws://websocket.example.com/ HTTP/1.1 Origin: http://example.com Connection: Upgrade Host: websocket.example.com Upgrade: websocket 去了哪里。我是否正确完成了 C# 或 JavaScript 中的握手?
  • JS端是正确的,由浏览器和WebSocket类型实现(正确发送初始握手并等待连接升级)。 C# 端不正确,因为它从未完成所需的握手。
  • 要么编写(最低限度)有效的实现(参见 RFC 等tools.ietf.org/html/rfc6455),要么使用了解如何接受 WS 握手/连接的现有有效库。最低限度有效的实现可能只是返回所需的 HTTP 和“升级”标头。
  • 特别是 RFC6455 的第 4.2 节 - tools.ietf.org/html/rfc6455#section-4.2
  • 看起来 HttpListener 工作正常。非常感谢你。
猜你喜欢
  • 1970-01-01
  • 2019-06-11
  • 2014-12-16
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
  • 2023-03-05
  • 2023-04-02
相关资源
最近更新 更多