我在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_DONTWAIT
,MSG_WAITALL
,while($bytes > 0){ ... }
。但它们都进入无限循环,其余代码(在socket_recv下面)不再运行。
我该如何解决这个问题? (我在我的localhost中的wampserver中测试)
可能的解决方案
当我绞尽脑汁解决这个问题时,我想到了一个临时解决方案:
如果我们无法发送大于5800个字符的文本,我可以尝试 在客户端制作一个代码,将字符切割成小于5800的字符 字符并将这些部分分别发送到套接字 参数,表示此条目被截断,并在套接字I内 可以尝试过滤它们并加入角色。
答案 0 :(得分:0)
在那段时间里我意识到很多测试,我意识到了一些事情。
邮件已加密
在服务器上收到邮件的邮件在标准RFC 6455中加密后,如果您在变量echo
中运行$buffer
,则会看到以下内容:{{1 }},×RÄeÐÀlÓ[Ç)
...实施例:
对于字符串
Ó[ÁhÒß
,您会看到stackoverflow
,如果再次插入该字符串,则会看到不同的哈希值,但它们遵循加密标准,例如:for stringiuj87xz
我会为两个(stack stack
和rrtfgh
)设置相同的哈希值,但是如果我再次发送到套接字我会看到之前的差异哈希值,但两者的哈希值相同(rrtfgh
和mmjsht
)。
消息以块的形式接收
当我在屏幕上显示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
内连接)。
我还没有测试过这段代码,似乎就是这样,在我完成代码测试之后我会回到这里发布完整的代码。