c++ WebSocket连接由于子协议不匹配而终止

hmmo2u0o  于 2023-07-01  发布在  其他
关注(0)|答案(1)|浏览(217)

我正在用C#实现一个WebSocket客户端,用于用C++编写的现有websockocket服务器。服务器使用两个子协议:“mySubprotocolOne”、“mySubprotocolTwo”。我不能碰服务器代码。
要启动WebSocket连接,我使用以下代码:

var wsClient = new ClientWebSocket();
wsClient.Options.AddSubProtocol("mySubprotocolOne");
await wsClient.ConnectAsync(new Uri(wsUri), cToken);

我在wireshark中观察到以下行为:

Client -> Server | HTTP | GET / HTTP/1.1
Server -> Client | HTTP | HTTP/1.1 101 Switching Protocols
Client -> Server | TCP | [FIN, ACK]
Server -> Client | TCP | [ACK]
Server -> Client | TCP | [FIN, ACK]

服务器正在接受请求,但我的客户端立即终止了连接。在客户端,我得到以下异常:
无法建立WebSocket主机ws://ip:port/ - System.Net.WebSockets.WebSocketException(0x 80004005):WebSocket客户端请求请求“mySubprotocolOne”协议,但服务器仅接受“mySubprotocolOne,mySubprotocolTwo”协议
来自服务器的响应头看起来像这样:

HTTP/1.1 101 Switching Protocols\r\n
Upgrade: WebSocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Accept: someBase64Key\r\n
Sec-WebSocket-Protocol: mySubprotocolOne,mySubProtocolTwo\r\n
\r\n

我所尝试的:

  • 添加行
wsClient.Options.AddSubProtocol("mySubProtocolTwo");

导致相同的行为。根据RFC,子协议不包含任何禁止的字符.如果子协议名称有问题,服务器将不会响应“HTTP/1.1 101 Switching Protocols”。
我是否忽略了客户端抛出此异常的任何明显原因?您对进一步调试有什么建议?

hfyxw5xn

hfyxw5xn1#

好吧,问题是在服务器上实现WebSocket协议时出错了。这是一个自己动手的实现,当时还没有可靠的C++ WebSocket库。
以下是RFC关于子协议协商的说明:
客户端可以请求服务器使用特定的子协议,方法是将|Sec-WebSocket协议|在握手中。如果指定,则服务器需要在其响应中包含相同的字段和所选子协议值中的一个,以便建立连接
因此,客户端在其请求中提供可能的子协议,服务器选择其中一个并将其放入响应头中。在我的例子中,服务器用所有可用的子协议进行响应,这是没有意义的,因为客户端仍然不知道要使用哪一个。
C# WebSocket库将响应头中的 *Sec-WebSocket-Protocol字段 * 的完整字符串解释为一个协议名称,当然该名称与任何请求的协议都不匹配。因此它抛出一个异常。

相关问题