これはおそらくおなじみのすすり泣きの話です。しかし、世の中にはたくさんあり、私はあまりにも無知で答えが見つからないので、助けていただければ助かります.
したがって、私は lemmingzshadow の phpwebsocket を使用しています (慣れていない場合は、Google で簡単に取り上げることができます)。私が知る限り、彼がリリースしたバージョンにはバグがあり、Chrome 20.+ が現在使用している標準に従っていません。ハンドシェイクとセキュリティキーに関係がありますが、それが私が行き詰まっているところです。他の質問に基づいて次の情報を提供する必要があることは承知しています。この問題を理解して修正するのに役立つことを願っています:
Chromeが受け取るヘッダーは次のとおりです(編集済み。サーバーにメッセージを2回投稿したようです):
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: aWXrpLOnEm15mE8+w1zG05ad01k=
Sec-WebSocket-Protocol: QuatroDuo
私のサーバーが受け取るヘッダーは次のとおりです。
Upgrade: websocket
Connection: Upgrade
Host: gumonshoe.net:8000
Origin: http://gumonshoe.net
Sec-WebSocket-Key: v3+iw0U78qkwZnp+RWTu3A
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame
Cookie は必要ないと思いますが、間違っている場合は修正してください。
この次の部分を行うのは嫌いですが、何もせずに後で戻る必要があるよりは、すべてを貼り付けたほうがよいと思います。これは、ハンドシェイクを読み取って解釈し、新しいハンドシェイクを送信するコードの一部です。
ヘルプは高く評価されています:
<?PHP
private function handshake($data)
{
$this->log('Performing handshake\r\n\r\n' . $data);
$lines = preg_split("/\r\n/", $data);
// check for valid http-header:
if(!preg_match('/\AGET (\S+) HTTP\/1.1\z/', $lines[0], $matches)) {
$this->log('Invalid request: ' . $lines[0]);
$this->sendHttpResponse(400);
stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
return false;
}
// check for valid application:
$path = $matches[1];
$this->application = $this->server->getApplication(substr($path, 1));
if(!$this->application) {
$this->log('Invalid application: ' . $path);
$this->sendHttpResponse(404);
stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
$this->server->removeClientOnError($this);
return false;
}
// generate headers array:
$headers = array();
foreach($lines as $line)
{
$line = chop($line);
if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
{
$headers[$matches[1]] = $matches[2];
}
}
// check for supported websocket version:
if(!isset($headers['Sec-WebSocket-Version']) || $headers['Sec-WebSocket-Version'] < 6)
{
$this->log('Unsupported websocket version.');
$this->sendHttpResponse(501);
stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
$this->server->removeClientOnError($this);
return false;
}
// check origin:
if($this->server->getCheckOrigin() === true)
{
$origin = (isset($headers['Sec-WebSocket-Origin'])) ? $headers['Sec-WebSocket-Origin'] : false;
$origin = (isset($headers['Origin'])) ? $headers['Origin'] : $origin;
if($origin === false)
{
$this->log('No origin provided.');
$this->sendHttpResponse(401);
stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
$this->server->removeClientOnError($this);
return false;
}
if(empty($origin))
{
$this->log('Empty origin provided.');
$this->sendHttpResponse(401);
stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
$this->server->removeClientOnError($this);
return false;
}
if($this->server->checkOrigin($origin) === false)
{
$this->log('Invalid origin provided. : ' . $origin . ' Legal options were:');
$gumk = 0;
foreach(array_keys($this->server->getAllowedOrigins()) as $lo) {
$this->log( '[' . $gumk++ . '] : ' . $lo);
}
$this->sendHttpResponse(401);
stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
$this->server->removeClientOnError($this);
return false;
}
}
// do handyshake: (hybi-10)
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$response = "HTTP/1.1 101 Switching Protocols\r\n";
$response.= "Upgrade: websocket\r\n";
$response.= "Connection: Upgrade\r\n";
$response.= "Sec-WebSocket-Accept: " . $secAccept . "\r\n";
$response.= "Sec-WebSocket-Protocol: " . substr($path, 1) . "\r\n\r\n";
if(false === ($this->server->writeBuffer($this->socket, $response)))
{
return false;
}
$this->handshaked = true;
$this->log('Handshake sent');
$this->application->onConnect($this);
// trigger status application:
if($this->server->getApplication('status') !== false)
{
$this->server->getApplication('status')->clientConnected($this->ip, $this->port);
}
return true;
}
次のエラーを受け取り、
Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch
私はこのレベルのサーバーのデバッグにほとんど経験がないため、ドキュメント/仕様にリンクするよりも詳細な回答をいただければ幸いです。