Chrome 20 websocket 握手
Posted
技术标签:
【中文标题】Chrome 20 websocket 握手【英文标题】:Chrome 20 websocket handshake 【发布时间】:2012-07-02 20:27:57 【问题描述】:我正在使用 lemmingzshadow (web) 的 php Websocket 服务器。到目前为止,一切都很好。
更新到 chrome 20 后,如果我想与服务器握手,它会以这个错误结束
Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch
来自 chrome 20 的标题
GET /demo HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: gomokulive.eu:8001
Origin: http://www.gomokulive.eu
Sec-WebSocket-Key: s+AMQQu4Q10xH2AKy49byg==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
发回的标头:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: dMCVYKkF5VRrIouWFW7EYdvfD28=
Sec-WebSocket-Protocol: demo
我认为问题在于 Chrome 20 中的“Sec-WebSocket-Extensions: x-webkit-deflate-frame”标头。
知道如何让它再次工作吗?
【问题讨论】:
自昨天的升级以来,Chrome 20 Websockets 似乎存在问题,主要是在 Windows 平台上……如果可以的话,恢复到以前的版本,否则谷歌几乎肯定会很快发布补丁因为它可以防止访问 sto 漫游配置文件 我有在 websockets 上运行的游戏,所以它不像“恢复到以前的版本”。如果 ws 客户端无法连接用户将只看到错误消息:/ 现在我回到 flash 实现 github.com/gimite/web-socket-js @MarkBaker 有关于此的任何新信息?错误或功能?谢谢 【参考方案1】:服务器违反了 WebSocket 协议。 Chrome 很可能只是在版本 20 中更正确地遵守标准,这暴露了服务器中的错误。
问题在于服务器在响应中发回了“Sec-WebSocket-Protocol”标头,但这仅在客户端在请求中发送相同标头时才合法。如果客户端没有发送 Sec-WebSocket-Protocol,那么服务器应该在响应中省略头部。
请参阅Section 4.2.2 of rfc6455 中第 22 页的 /subprotocol/ 描述
【讨论】:
看来你说到点子上了 :) 我明天会更仔细地测试一下【参考方案2】:php-websocket 的快速修复方法是:
$response.= "Sec-WebSocket-Accept: " . $secAccept . "\r\n";
if (isset($headers['Sec-WebSocket-Protocol']))
$response.= "Sec-WebSocket-Protocol: " . substr($path, 1) . "\r\n";
$response .= "\r\n";
【讨论】:
【参考方案3】:一个简单的解决方法是在do_handshake时添加Sec-WebSocket-Accept
信息,代码如下:
list($resource,$host,$origin,$key) = $this->getheaders($buffer);
$accept = base64_encode(SHA1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: WebSocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $origin\r\n" .
"WebSocket-Location: ws://$host$resource\r\n".
"Sec-WebSocket-Accept: " . $accept . "\r\n\r\n";
$this->handshakes[$socket_index] = true;
socket_write($socket,$upgrade,strlen($upgrade));
在哪里,
$accept = base64_encode(SHA1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
$key 是 Sec-WebSocket-Key
从 $buffer 得到的,你可以 print_r($buffer) 看看。
希望这可以解决您的问题..
【讨论】:
258EAFA5-E914-47DA-95CA-C5AB0DC85B11的值从何而来? 不知道是固定帖,试试看。我不记得确切,因为它是一年前。以上是关于Chrome 20 websocket 握手的主要内容,如果未能解决你的问题,请参考以下文章