JS Websocket 卡在连接到 TCPListener 的状态 - VB.net

JS Websocket stuck in state CONNECTING to TCPListener - VB.net

注意:我发现最接近我的问题是this one,但答案是通过等待 readyState 的代理函数发送数据1.尽管标题非常相似,但这不是该问题的副本;我知道我的问题在于我的服务器没有将数据传回客户端,但我不知道要传递什么。

详情:

我在我的服务器程序中定义了一个 TCP 侦听器作为 New TcpListener(ipAd, 8001),我编写了一个客户端程序作为 New TcpClient() 来连接到服务器。这些程序按预期工作,一旦建立连接,客户端就可以向服务器发送数据。

完成客户端和服务器后,我开始开发一个 Web 界面作为客户端,这样我就可以从任何设备向套接字发送数据。这是 websocket 的 javascript 代码:

    console.log("Attempting to connect...");

    ws = new WebSocket('ws://192.168.0.10:8001/');

    ws.onopen = function(msg) {
        console.log('Connection successfully opened');
    };

    ws.onmessage = function(msg) {
        console.log(msg);
    };

    ws.onclose = function(msg) {
        console.log("Closed.");
    }

    ws.error = function(err){
        console.log(err);
    }

加载网页时,我在服务器控制台应用程序中看到已建立连接。这是输出:

GET / HTTP/1.1
Host: 192.168.0.10:8001
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-
cache
Upgrade: websocket
Origin: null
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows
 NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36
Accept-Enc
oding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Sec-WebSocket-Key: key_here
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

如此清楚地发送和接收了 HTTP headers;然而,我的服务器(目前)没有向客户端发送任何东西,所以当我尝试从 websocket 发出 ws.send("test"); 时,我在控制台收到一个错误:

Uncaught InvalidStateError: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.

我的问题:我需要从我的服务器发回客户端什么来完成握手,这样我才能用ws.send();发送数据?

您需要实现 webSocket 的 server-side(或使用可以为您执行此操作的 webSocket 库)。这里是 one sample implementation in VB. And a similar question with sample code.

一个 webSocket 连接是这样工作的:

  1. 客户端向服务器发出 http 请求,自定义 header 请求升级到 webSocket 协议

  2. 服务器响应升级到 webSocket 成功并使用随机生成的安全密钥。

  3. 服务端发送响应,客户端收到后,双方切换为webSocket数据帧格式,用于以后的数据

  4. 此外,还有一些必须支持的强制消息,例如 ping 和 pong 以支持客户端将使用的保持连接心跳来了解连接是否仍然存在。

有关示例响应和 webSocket 数据帧格式的描述,请参阅 this article

此外,浏览器默认强制实施 same-origin 限制,因此如果您尝试从浏览器连接到与 Javascript 所在网页不同的来源,那么您将需要来自您的服务器的适当 CORS headers 以启用跨源连接。


这是一个示例连接:

客户发送这个:

GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

服务器响应如下:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

然后,数据框看起来像这样:

0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+

当然,webSocket RFC 官方规范是here