服务器端 Websocket 握手失败,出现'Sec-WebSocket-Accept mismatch'



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

我根据 RFC 实现了标头创建,但在谷歌浏览器(版本 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 Protocolsrn";
   $h .= "Upgrade: websocketrn";
   $h .= "Connection: Upgradern";
   $h .= "Sec-WebSocket-Accept: $acceptrn";
   $h .= "Sec-WebSocket-Protocol: 13rnrn";
   echo $h;
   // send header to client
   socket_write($sock,$h,strlen($h));
}
?>

我在这里错过了什么吗?

提前感谢!

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

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

最新更新