Serverside Websocket握手失败,出现'Sec-WebSocket-Accept mismatch'

时间:2014-02-09 11:39:06

标签: php google-chrome websocket

我尝试在PHP中创建一个使用当前WebSocket协议13的Websocket服务器。

我根据RFC实现了标头创建,但在Google Chrome(第31版)中,它仍然失败并显示错误消息Error during WebSocket handshake: Sec-WebSocket-Accept mismatch。 Firefox至少显示响应,但它也不会触发客户端onOpen事件。

下面是PHP中的一个最小测试服务器,其中包含用于创建标题的代码:

<?php

$srv = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($srv, '0.0.0.0', 50500);
socket_listen($srv, 10);

for(;;){

    $sock = socket_accept($srv);

    // get header
    $header = socket_read($sock, 1024);

    // extract key
    $keys = array();
    preg_match_all("/Sec-WebSocket-Key:\s*(.*)\s*/", $header, $keys);

    if(count($keys) < 1){
         // Not a valid Websocket Handshake
         socket_close($sock);
         continue;
    }

   // create hash according to RFC
   $key = $keys[1][0];
   $accept = base64_encode(SHA1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));

   // create header
   $h = "HTTP/1.1 101 Switching Protocols\r\n";
   $h .= "Upgrade: websocket\r\n";
   $h .= "Connection: Upgrade\r\n";
   $h .= "Sec-WebSocket-Accept: $accept\r\n";
   $h .= "Sec-WebSocket-Protocol: 13\r\n\r\n";

   echo $h;

   // send header to client
   socket_write($sock,$h,strlen($h));

}

?>

我在这里遗漏了什么吗?

提前致谢!

1 个答案:

答案 0 :(得分:0)

正则表达式/Sec-WebSocket-Key:\s*(.*)\s*/将在匹配的内容中包含\r个字符(.匹配\r但不包括\n),因此您的$key变量将具有错误的值。你需要找出一个正则表达式,它匹配除最后的\r\n序列之外的所有内容。

此外,如果客户端将其包含在请求中,则服务器应仅包含Sec-WebSocket-Protocol属性,并且该值必须是客户端Sec-WebSocket-Protocol属性中请求的协议之一。否则客户端将给出错误,请参阅RFC 6455