socket_recv仅接收1448个字节


socket_recv receiving only 1448 bytes?

我在socket_recv接收客户端发送到服务器的完整数据时遇到了一些问题,接收数据的代码如下:

while(true) {
      $changedSockets = $this->sockets;
      $result = socket_select($changedSockets,$write,$except,0);
      foreach($changedSockets as $socket){
          $buffer = '';
          $message = '';
          $bytes = @socket_recv($socket, $buffer, 4096, 0);

              echo "Lenght: (".$bytes.length.")";

            if ($bytes === false) {
            $error = self::getLastError( $this->socket );
            trigger_error( 'Failed to receive data from client #'.$client->id.': '.$error->message.' ['.$error->code.']', E_USER_WARNING );
            continue;
            }
          $len = ord( $buffer[1] ) & 127;
          $masks = null;
          $data = null;
                    if ( $len === 126 ) {
                        $masks = substr( $buffer, 4, 4 );
                        $data = substr( $buffer, 8 );
                    }
          elseif ( $len === 127 ) {
                        $masks = substr( $buffer, 10, 4 );
                        $data = substr( $buffer, 14 );
                    }
          else {
                        $masks = substr( $buffer, 2, 4 );
                        $data = substr( $buffer, 6 );
                    }
                    for( $index = 0; $index < strlen( $data ); $index++ ) {
                        $message .= $data[$index] ^ $masks[$index % 4];
                    }
                    if ( $bytes == 0 ) {
                        $this->disconnectClient( $socket );
                    }   
        }
        }
        }

这个代码运行得很好,但有一个问题:如果我发送的文本超过5800个字符,我的代码就不会收到全文(只有一小部分)。

为了了解发生了什么,我只插入下面的代码,看看有多少字节:

$bytes = @socket_recv($socket, $buffer, 4096, 0);
echo "Lenght: (".$bytes.length.")";

我注意到,当您发送小于5800个字符的文本时,字节的大小与客户端发送的字节大小相同,现在,当文本超过5800个字时,socket_recv的长度保持在1448个字符(如果我将值4096更改为更高的值,则会得到更多字符,但如果我打开php,则会产生内存问题)

为了解决这个问题,我尝试了很多方法,比如使用:MSG_DONTWAITMSG_WAITALLwhile($bytes > 0){ ... }。但它们都进入了一个无限循环,使得代码的其余部分(socket_recv下面)不再运行。

我该如何解决这个问题?(我正在本地主机的wampserver中进行测试)

可能的解决方案

当我绞尽脑汁解决这个问题时,我想到了一个临时的解决方案:

如果我们不能发送大于5800个字符的文本,我可以尝试在客户端制作一个代码,将字符切成小于5800的小块字符,并使用参数,表示该条目被截断,并且在套接字I可以尝试过滤它们并加入字符。

在那段时间里我实现了许多测试,我实现了一些事情。

接收的消息经过加密

当消息在服务器上接收时,它们在标准RFC 6455中被加密,如果您在变量$buffer中运行echo,您将看到以下内容:×RÄeÐÀlÓ[Ç)Ó[ÁhÒß。。。示例:

对于字符串stackoverflow,你会看到iuj87xz,如果你再次插入该字符串,你会发现一个不同的哈希,但它们遵循加密标准,例如:对于字符串stack stack,我会为两者使用相同的哈希(rrtfghrrtfgh),但如果我再次发送到套接字,我会看到一个与以前不同的散列,但两者的散列都相同(mmjshtmmjsht)。

消息以块形式接收

当我在屏幕上显示$buffer并发送一条超过10000个字符的文本时,我看到foreach($changedSockets as $socket)It一直被调用,直到消息的所有部分都被传递为止。

如果你看到我的代码,你会看到每一条新消息都被解密了。但我遇到了一个问题,在解密的第一个块消息中,我可以清楚地读取它(读取我发送到套接字的文本),但其他块不会发生这种情况。

分析变量$buffer中包含的哈希,我可以注意到第一个块中有一些不同,例如:让我们将此文本发送到服务器:Hello Hello Hello....(repeated 10000X)

区块1:þ@¨¿7ÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)

区块2:×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ

块1解密:Hello Hello Hello Hello...

块2解密:LLE LLE LLE LLE LLE...

注意到区别了吗?看起来我在块1中得到了一个其他块中不存在的不同入口代码。它让我想起了转换为base64的图像,它在哈希之前有一个启动代码:data:image/png;base64,......,并且在没有启动代码的情况下不起作用,因为这不起作用(正如我们在上面看到的)。

可能的解决方案

我可以将消息发送到套接字,消息的长度如下:在服务器端的"16049" Hello Hello Hello....,我会取这个数量,除以4096,这是我的Socket_Recv的长度,这样我就会得到等于4的结果,这是接收完整消息的所有块所需的重复次数。

然后,在收到最后一个块之前,我不会运行代码来解密消息(同时,我在$buffer中获取哈希并进行连接)。

我还没有测试过这个代码,似乎就是这样,在我完成代码测试后,我会回到这里发布完整的代码。