socket_recv只接收1448个字节?

时间:2016-05-10 11:24:28

标签: php sockets

我在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下面)不再运行。

我该如何解决这个问题? (我在我的localhost中的wampserver中测试)

  

可能的解决方案

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

  

如果我们无法发送大于5800个字符的文本,我可以尝试   在客户端制作一个代码,将字符切割成小于5800的字符   字符并将这些部分分别发送到套接字   参数,表示此条目被截断,并在套接字I内   可以尝试过滤它们并加入角色。

1 个答案:

答案 0 :(得分:0)

在那段时间里我意识到很多测试,我意识到了一些事情。

邮件已加密

在服务器上收到邮件的邮件在标准RFC 6455中加密后,如果您在变量echo中运行$buffer,则会看到以下内容:{{1 }},×RÄeÐÀlÓ[Ç) ...实施例:

  

对于字符串Ó[ÁhÒß,您会看到stackoverflow,如果再次插入该字符串,则会看到不同的哈希值,但它们遵循加密标准,例如:for string iuj87xz我会为两个(stack stackrrtfgh)设置相同的哈希值,但是如果我再次发送到套接字我会看到之前的差异哈希值,但两者的哈希值相同( rrtfghmmjsht)。

消息以块的形式接收

当我在屏幕上显示mmjsht并发送超过10000个字符的文本时,我看到$buffer继续调用它,直到消息的所有部分都已发送。

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

分析变量foreach($changedSockets as $socket)中包含的哈希我可能会注意到第一个块中的不同内容,例如:让我们将此文本发送到服务器:$buffer

  

第1区:Hello Hello Hello....(repeated 10000X)

     

第2栏:þ@¨¿7ÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)

     

Block 1 Decrypted:×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ[Ç)×RÄeÐÀlÓ

     

Block 2 Decrypted:Hello Hello Hello Hello...

注意区别?看起来我在块1中得到了一个在其他块中不存在的不同的入口代码。它让我想起转换成base64的图像,它在哈希值之前有一个引导代码:LLE LLE LLE LLE LLE...并且在没有引导代码的情况下不能使用部分哈希值,因为这不起作用(如上所述)。

可能的解决方案

我可以将消息发送到具有该消息长度的套接字,如下所示:data:image/png;base64,......在服务器端我将这个数量除以"16049" Hello Hello Hello....,这是我{的长度{1}},我将得到的结果等于4,这就是我必须弥补接收完整信息的所有块的重复次数。

然后我不会运行代码来解密消息,直到我收到最后一个块(同时我正在使用哈希并在4096内连接)。

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