PHP Websocket 服务器 - 在 socket_recv 中处理更多帧
PHP Websocket server - Handle more frames in socket_recv
希望之前这里没有解决这个问题,但我真的很想寻找答案!
我在 PHP 服务器中通过 socket_recv 接收帧时遇到问题。当我一次从客户端发送多于 1 条消息时出现问题(例如循环)。根据流长度,它是匹配帧数,但我无法正确取消屏蔽帧,我的取消屏蔽功能 return 仅在第一帧。我正在使用我在此处找到的 php 服务器的一部分,对于一条消息,它工作正常,但是当我一次收到更多消息时,它并没有揭开所有的面纱。
我尝试添加循环以遍历所有帧,但我无法找到帧的结尾并继续到其他帧。
这是服务器的主要时间:
while (true) {
//manage multipal connections
$changed = $clients;
//returns the socket resources in $changed array
socket_select($changed, $null, $null, 0, 10);
//check for new socket
if (in_array($socket, $changed)) {
$socket_new = socket_accept($socket); //accpet new socket
$clients[] = $socket_new; //add socket to client array
$header = socket_read($socket_new, 10240); //read data sent by the socket
perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
socket_getpeername($socket_new, $ip); //get ip address of connected socket
$response = mask(json_encode(array('type' => 'system', 'status' => true, "id" => "SRV_CONNECTED", 'message' => $ip . ' connected'))); //prepare json data
send_message($response); //notify all users about new connection
//make room for new socket
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
foreach ($changed as $changed_socket) {
while (@socket_recv($changed_socket, $buf, 1024, 0) >= 1) {
$received_text = unmask($buf); //unmask data
$tst_msg = json_decode($received_text, true); //json decode
$response_text = parse_msg($tst_msg, $changed_socket);
break 2; //exit this loop
}
$buf = @socket_read($changed_socket, 10240, PHP_NORMAL_READ);
if ($buf === false) { // check disconnected client
// remove client for $clients array
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
//notify all users about disconnected connection
$response = mask(json_encode(array('type' => 'system', 'message' => $ip . ' disconnected')));
send_message($response);
}
}
我需要根据在@socket_recv 中接收到的帧数来调用parse_msg,它应该被return unmask 函数编辑。
这是取消屏蔽功能:
function unmask($payload){
$decMessages = Array();
do { // This should be running until all frames are unmasked and added to $decMessages Array
$length = ord($payload[1]) & 127;
if($length == 126) {
$masks = substr($payload, 4, 4);
$data = substr($payload, 8);
$len = (ord($payload[2]) << 8) + ord($payload[3]);
}elseif($length == 127) {
$masks = substr($payload, 10, 4);
$data = substr($payload, 14);
$len = (ord($payload[2]) << 56) + (ord($payload[3]) << 48) +
(ord($payload[4]) << 40) + (ord($payload[5]) << 32) +
(ord($payload[6]) << 24) +(ord($payload[7]) << 16) +
(ord($payload[8]) << 8) + ord($payload[9]);
}else {
$masks = substr($payload, 2, 4);
$data = substr($payload, 6);
$len = $length;
}
$text = '';
for ($i = 0; $i < $len; ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
$decMessages[] = $text;
// Here is problem. It doesn't put correct substr to $payload, so it could run again on stream shorted by last message
$payload = substr($payload, $length, strlen($payload));
}while (($len < strlen($data)) and $countert < 10);
return $decMessages;
}
我想我的问题出在这里:$payload = substr($payload, $length, strlen($payload));我在哪里放错了流的其余部分?
所以我的问题是:
为什么@socket_recvreturn不止一帧
我如何更改我的 unmask 功能以遍历所有帧,而不仅仅是第一帧
我将非常感谢任何帮助,因为我为此付出了更多的努力。
提前致谢
克拉拉!
所以,我找到了解决方案。正如我所想,问题是一次接收中有多个帧。我需要编辑我的取消屏蔽功能来检查流中是否还有帧。
基本上,我得到的是正确的,但
中的 $length
$payload = substr($payload, $length, strlen($payload));
错了。而不是 $length 我使用 $len + 8, 14 od 6 取决于 $length。我不确定如何描述为什么会这样,但我相信有人会。就这样。现在它可以正常工作了!
谢谢!
希望之前这里没有解决这个问题,但我真的很想寻找答案!
我在 PHP 服务器中通过 socket_recv 接收帧时遇到问题。当我一次从客户端发送多于 1 条消息时出现问题(例如循环)。根据流长度,它是匹配帧数,但我无法正确取消屏蔽帧,我的取消屏蔽功能 return 仅在第一帧。我正在使用我在此处找到的 php 服务器的一部分,对于一条消息,它工作正常,但是当我一次收到更多消息时,它并没有揭开所有的面纱。
我尝试添加循环以遍历所有帧,但我无法找到帧的结尾并继续到其他帧。
这是服务器的主要时间:
while (true) {
//manage multipal connections
$changed = $clients;
//returns the socket resources in $changed array
socket_select($changed, $null, $null, 0, 10);
//check for new socket
if (in_array($socket, $changed)) {
$socket_new = socket_accept($socket); //accpet new socket
$clients[] = $socket_new; //add socket to client array
$header = socket_read($socket_new, 10240); //read data sent by the socket
perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
socket_getpeername($socket_new, $ip); //get ip address of connected socket
$response = mask(json_encode(array('type' => 'system', 'status' => true, "id" => "SRV_CONNECTED", 'message' => $ip . ' connected'))); //prepare json data
send_message($response); //notify all users about new connection
//make room for new socket
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
foreach ($changed as $changed_socket) {
while (@socket_recv($changed_socket, $buf, 1024, 0) >= 1) {
$received_text = unmask($buf); //unmask data
$tst_msg = json_decode($received_text, true); //json decode
$response_text = parse_msg($tst_msg, $changed_socket);
break 2; //exit this loop
}
$buf = @socket_read($changed_socket, 10240, PHP_NORMAL_READ);
if ($buf === false) { // check disconnected client
// remove client for $clients array
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
//notify all users about disconnected connection
$response = mask(json_encode(array('type' => 'system', 'message' => $ip . ' disconnected')));
send_message($response);
}
}
我需要根据在@socket_recv 中接收到的帧数来调用parse_msg,它应该被return unmask 函数编辑。
这是取消屏蔽功能:
function unmask($payload){
$decMessages = Array();
do { // This should be running until all frames are unmasked and added to $decMessages Array
$length = ord($payload[1]) & 127;
if($length == 126) {
$masks = substr($payload, 4, 4);
$data = substr($payload, 8);
$len = (ord($payload[2]) << 8) + ord($payload[3]);
}elseif($length == 127) {
$masks = substr($payload, 10, 4);
$data = substr($payload, 14);
$len = (ord($payload[2]) << 56) + (ord($payload[3]) << 48) +
(ord($payload[4]) << 40) + (ord($payload[5]) << 32) +
(ord($payload[6]) << 24) +(ord($payload[7]) << 16) +
(ord($payload[8]) << 8) + ord($payload[9]);
}else {
$masks = substr($payload, 2, 4);
$data = substr($payload, 6);
$len = $length;
}
$text = '';
for ($i = 0; $i < $len; ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
$decMessages[] = $text;
// Here is problem. It doesn't put correct substr to $payload, so it could run again on stream shorted by last message
$payload = substr($payload, $length, strlen($payload));
}while (($len < strlen($data)) and $countert < 10);
return $decMessages;
}
我想我的问题出在这里:$payload = substr($payload, $length, strlen($payload));我在哪里放错了流的其余部分?
所以我的问题是: 为什么@socket_recvreturn不止一帧 我如何更改我的 unmask 功能以遍历所有帧,而不仅仅是第一帧
我将非常感谢任何帮助,因为我为此付出了更多的努力。
提前致谢 克拉拉!
所以,我找到了解决方案。正如我所想,问题是一次接收中有多个帧。我需要编辑我的取消屏蔽功能来检查流中是否还有帧。
基本上,我得到的是正确的,但
中的 $length$payload = substr($payload, $length, strlen($payload));
错了。而不是 $length 我使用 $len + 8, 14 od 6 取决于 $length。我不确定如何描述为什么会这样,但我相信有人会。就这样。现在它可以正常工作了!
谢谢!