我试图用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。