【问题标题】:Safari Websocket Handshake ErrorSafari Websocket 握手错误
【发布时间】:2017-01-05 23:09:12
【问题描述】:

我正在为一个学校项目构建自己的 Http Server,并内置对 Websockets 的支持。

我主要在 Chrome 上测试了一切,一切看起来都不错,但我在 Safari (10.0.2) 上遇到了问题。

当建立握手 WebSocket connection to 'ws://192.168.0.213' failed: Status line contains non-ASCII character 在开发控制台中显示为错误时,请记住,Chrome 可以正常工作。

这是交换的标头

请求标头(Safari => 服务器)

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 192.168.0.213
Origin: http://192.168.0.213
Cookie: session=MDQ5M2UzYTctODg5NC00ZTEwLWJlOWEtYjBiZTRkNzdiYTRj
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: 9/Mj26XS0JxG+Y+lDTvMcQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/602.3.12 (KHTML, like Gecko) Version/10.0.2 Safari/602.3.12

响应标头(服务器 => Safari)

HTTP/1.1 101 Switching Protocols
Connection:Upgrade
Upgrade:websocket
Sec-WebSocket-Accept:rpx9CefKAgOdM7RzjhLuWEcCIso=

原始响应标头

[72][84][84][80][47][49][46][49][32][49]
[48][49][32][83][119][105][116][99][104][105]
[110][103][32][80][114][111][116][111][99][111]
[108][115][13][10][67][111][110][110][101][99]
[116][105][111][110][58][85][112][103][114][97]
[100][101][13][10][85][112][103][114][97][100]
[101][58][87][101][98][115][111][99][107][101]
[116][13][10][83][101][99][45][87][101][98]
[83][111][99][107][101][116][45][65][99][99]
[101][112][116][58][53][120][86][118][113][57]
[52][121][97][53][84][56][51][88][65][82]
[115][78][119][74][69][88][97][78][97][108]
[99][61][13][10][13][10]

它是如何生成的(C#)

string handshakeString = $"HTTP/1.1 {(int)StatusCode.SwitchingProtocols} {StatusCode.SwitchingProtocols.GetStatusMessage()}" + Environment.NewLine
                                                 + "Connection:Upgrade" + Environment.NewLine
                                                 + "Upgrade:Websocket" + Environment.NewLine
                                                 + "Sec-WebSocket-Accept:" + Convert.ToBase64String($"{_initHeader["Sec-WebSocket-Key"]}258EAFA5-E914-47DA-95CA-C5AB0DC85B11".Sha1()) + Environment.NewLine
                                                 + Environment.NewLine;
byte[] handshake = Encoding.ASCII.GetBytes(handshakeString); // <- There is the ASCII part
await SendFrameData(OpCode.Text, handshake); // This frame neither gets fragmented or masked

我了解,标头的编码肯定存在问题,但此标头被编码为 ASCII 并以 OpCode 0x1(文本)发送到客户端,并且它在 Chrome 中工作。我是否缺少一些标题键/值?

谢谢, 大卫

【问题讨论】:

  • 显然它不全是 ASCII,否则 Safari 不会抱怨它。您的服务器代码是什么样的?实际传输的原始字节是什么样的?
  • @RemyLebeau 我刚刚添加了一些服务器代码和原始字节。
  • SendFrameData() 实际上是做什么的?在这个通信阶段,协议仍然是 HTTP,而不是 WebSocket,所以如果 SendFrameData(OpCode.Text, handshake) 没有发送 handshake as-is,而是将其包装在 WebSocket 框架中,那么你正在破坏通讯。在发送 HTTP 101 响应之后之前,您无法发送 WebSocket 帧。
  • 嗯,这正是我们所做的。此函数创建有效负载为握手的 Websocket 帧,Chrome 可以以某种方式处理它并接受 Websocket,但是 Safari 无法处理它。现在我将 Header 直接发送到套接字上,它可以完美地工作!谢谢!
  • 将握手响应包装在 WebSocket 帧中违反了 WebSocket 协议规范 RFC 6455。我不知道为什么 Chrome 会接受它,但 Safari 拒绝它是正确的做法。

标签: websocket safari handshake


【解决方案1】:

回答我自己的问题。谢谢雷米勒博!

握手被包裹在一个 Websocket 框架中。这违反了RFC 5455。所以握手需要直接通过socket发送。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多