PHP Websocket服务器-在socket_recv中处理更多帧

PHP Websocket服务器-在socket_recv中处理更多帧,php,websocket,server,frames,Php,Websocket,Server,Frames,希望这个问题以前没有解决,但我真的在努力寻找答案 我在PHP服务器中通过socket_recv接收帧时遇到问题。当我在同一时间(例如,在循环中)从客户端发送超过1条消息时,会出现问题。根据流长度,它的匹配帧计数,但我不能正确地取消帧的掩码,我的unmask函数只返回第一帧。我使用的是我在这里找到的php服务器的一部分,对于一条消息,它工作正常,但当我每次收到更多消息时,它并没有解除所有消息的掩码 我尝试添加循环以遍历所有帧,但我无法找到帧的结尾并继续到其他帧 这里是服务器的主要部分: while

希望这个问题以前没有解决,但我真的在努力寻找答案

我在PHP服务器中通过socket_recv接收帧时遇到问题。当我在同一时间(例如,在循环中)从客户端发送超过1条消息时,会出现问题。根据流长度,它的匹配帧计数,但我不能正确地取消帧的掩码,我的unmask函数只返回第一帧。我使用的是我在这里找到的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);
    }
}
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;
}
我需要调用parse_msg,通过@socket_recv中接收到的帧计数,这应该由unmask函数返回

这里是unmask函数:

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);
    }
}
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){
$decMessages=Array();
do{//应一直运行此操作,直到所有帧都被取消屏蔽并添加到$decMessages数组
$length=ord($payload[1])&127;
如果($length==126){
$masks=substr($payload,4,4);
$data=substr($payload,8);

$len=(ord($payload[2])所以,我找到了解决方案。正如我所想,问题是一次接收中有多个帧。我需要编辑我的unmask函数来检查流中是否还有帧

基本上,我所说的是对的,但长度是美元

$payload = substr($payload, $length, strlen($payload)); 
是错误的。我使用了$leng+8,而不是$leng+14 od 6取决于$length。我不知道如何描述这一点,但我相信有人会这样做。仅此而已。现在它已经正常工作了

谢谢