我尝试制作自己的PHP套接字服务器以使用HTML5 WebSocket API,但我无法执行握手步骤,我在这里阅读了[rfc6455][1]我的PHP服务器代码:
这里是Javascript代码:
var socket = new WebSocket("ws://127.0.0.1:1577/server.php");
socket.onopen = function (e) {
console.log("openned : "+e.readyState);
}
socket.onclose = function (e) {
console.log("Socket connection closed : "+e);
}
这里是PHP代码:
<?php
set_time_limit(0);
$adr = "127.0.0.1";
$port = 1577;
$m_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$msg = "Welcome...";
$cls = array();
socket_bind($m_sock, $adr, $port);
socket_listen($m_sock, 5);
echo "Server start...nn";
do{
$msgsock = socket_accept($m_sock);
array_push($cls, $msgsock);
echo "Connected...nn";
usleep(100);
//socket_write($msgsock, $msg, strlen($msg)); //this is the 'bug'
do{
if (false === ($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ))) {
echo "socket_read() fail :" . socket_strerror(socket_last_error($msgsock)) . "n";
break 2;
}
if(preg_match("/Sec-WebSocket-Key: (.*)/",$buf,$match)){
$key = base64_encode(hash("sha1",trim($match[1])."258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
$response_header = "HTTP/1.1 101 Switching Protocols"."rn".
"Upgrade: websocket"."rn".
"Connection: Upgrade"."rn".
"Sec-WebSocket-Accept: $key"."rnrn";
//SERVER RESPONSE ----
socket_write($msgsock,$response_header,strlen($response_header));
echo "handshake done...";
};
} while(1);
socket_close($msgsock);
} while(1);
我总是有这个错误:失败:WebSocket握手期间出错:无效状态行[1]: https://www.rfc-editor.org/rfc/rfc6455
这里是 HTTP 请求:
HTTP 请求 :
Accept-Encoding:gzip, deflate, sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,he;q=0.2
Cache-Control:no-cache
Connection:Upgrade
Cookie:__utma=96992031.134451192.1399804258.1402844967.1402848436.4; __utmz=96992031.1399804258.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _ga=GA1.4.134451192.1399804258; toolbarDisplay=hide
Host:127.0.0.1:1577
Origin:http://127.0.0.1
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:2yODScjZV/dap0DsDSWDFQ==
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36
这里是PHP服务器生成的响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: MDQ1NjFhMzc1YjY5MWQwNTU1ZGIzNDYyZmM0YTc1ODFhMDBlMzdmOQ==
你可以阅读Ratchet的源代码,看看他们是如何做到的。
这里有一个实现握手的类。
仅通过查看响应,您的 websocket 接受看起来似乎不对,看起来它太长了。 我知道这一点,因为我遇到了完全相同的问题。 如果这是我遇到的相同问题,那么问题就在这里:
SHA-1 传回十六进制值。 此值不能按原样简单地转换为 base64。 必须首先将十六进制值转换为 ascii 文本,然后才能对 ascii 文本值进行 base64 编码。
这里的简单答案是简单地获取从 SHA-1 传回的十六进制值并将其分解为 2 个字符的块。 取这 2 个字符,将它们转换为正常的十进制数字,然后查找该数字对应的 ascii 字符代码。
只需在哈希函数调用中添加第三个参数 'true'。 所以它看起来像这样:
hash("sha1",trim($match[1])."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true)
有关更多信息,PHP 哈希函数