我尝试在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));
}
?>
我在这里遗漏了什么吗?
提前致谢!
答案 0 :(得分:0)
正则表达式/Sec-WebSocket-Key:\s*(.*)\s*/
将在匹配的内容中包含\r
个字符(.
匹配\r
但不包括\n
),因此您的$key
变量将具有错误的值。你需要找出一个正则表达式,它匹配除最后的\r\n
序列之外的所有内容。
此外,如果客户端将其包含在请求中,则服务器应仅包含Sec-WebSocket-Protocol
属性,并且该值必须是客户端Sec-WebSocket-Protocol
属性中请求的协议之一。否则客户端将给出错误,请参阅RFC 6455。