Chrome 20 Websocket 握手

5
我正在使用lemmingzshadow的PHP Websocket服务器(网页)。一切都很好,直到现在。更新到Chrome 20之后,如果我想与服务器进行握手,它会以以下错误结束。
Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch 

Chrome 20的HTTP请求头

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 平台上出现了问题...如果可以的话,请恢复到以前的版本,否则 Google 几乎肯定会很快发布补丁,因为它阻止了对漫游配置文件的访问。 - Mark Baker
我有一个运行在Websockets上的游戏,所以它不像“恢复到以前的版本”。如果ws客户端无法连接,用户将只看到错误消息:/ 目前我回到了Flash实现 https://github.com/gimite/web-socket-js - m4recek
@MarkBaker 有关此事有任何新信息吗?是个 bug 还是一个特性?谢谢。 - Dejan Marjanović
3个回答

15
服务器违反了WebSocket协议。Chrome在版本20中更准确地遵守标准,这可能会揭示服务器中的一个错误。
问题在于服务器在响应中发送了“Sec-WebSocket-Protocol”头,但只有在客户端发送相同头部时才合法。如果客户端未发送Sec-WebSocket-Protocol,则服务器应在响应中省略该头。
请参阅rfc6455第4.2.2节第22页上的子协议/描述

1
看起来你说得对 :) 我明天会更仔细地测试。 - m4recek

3
一个快速修复 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";

1

一种简单的解决方法是在进行握手时添加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 是从 $buffer 获取的 Sec-WebSocket-Key,你可以使用 print_r($buffer) 来查看。

希望这可以解决您的问题。


258EAFA5-E914-47DA-95CA-C5AB0DC85B11这个值从哪里来? - Mazatec
1
我不确定这是固定的帖子,可以试一下。我记不清楚了,因为那是一年前的事了。 - navins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接