Socket_recv MSG_WAITALL不读取全长

时间:2014-01-27 13:16:35

标签: php sockets

我收到一个套接字响应,其中前4个字节是一个压缩的int,表示要接收的消息的最后部分。我们通过MSG_WAITALL接收它,它只在关闭连接之前收到一定数量的字节。 PHP手册说这是正常的“如果信号被捕获”。我如何获得完整的消息,$i["val"]长?

$sock = socket_create(AF_INET, SOCK_STREAM, 0);
socket_connect($sock , $server , 4656);
socket_recv($sock, $i, 4, MSG_WAITALL);
$i=unpack('Nval', $i);
socket_recv($sock, $buf, $i["val"], MSG_WAITALL);

具体来说它只读取2916bytes。如果$i["val"]小于该值,则读取正确,否则最大值为2916字节。

即使我循环,它也无法正确读取,除非我一次以1字节循环,我认为这不是正确的方法。这是一个2045b /循环的循环。

$len=$i[val];
echo 'Total Len: ' . $len . PHP_EOL;
if($len>=2045){
    $loops=floor($len/2045);
    echo 'Total Loops: ' . $loops . PHP_EOL;
    $last_loop=$len-(2045*$loops);
    echo 'Last Loop: ' . $last_loop . PHP_EOL;
    for($x=1; $x<=$loops; $x++){
        socket_recv($sock, $buf, 2045, MSG_WAITALL);
        $reply.=$buf;
    }
    socket_recv($sock, $buf, $last_loop, MSG_WAITALL);
    $reply.=$buf;
}else{
    socket_recv($sock, $buf, $len, MSG_WAITALL);
    $reply.=$buf;
}
echo 'Total Received: ' . strlen($reply) . PHP_EOL;

1 个答案:

答案 0 :(得分:0)

以下是一些未经测试的代码:

<?php

$sock = socket_create(AF_INET, SOCK_STREAM, 0);
socket_connect($sock, $server, 4656);

$len = 0;
$reply = '';

do {
    $status = socket_recv($sock, $buffer, 2048, 0);

    if (!$len) {
        $i = unpack('Nval', substr($buffer, 0, 4));
        $len = $i['val'];
        $buffer = substr($buffer, 4);
        echo 'Total Len: ' . $len . PHP_EOL;
    }

    $reply .= $buffer;

    if ($status === false) {
        $errorcode = socket_last_error();
        $errormsg = socket_strerror($errorcode);
        echo 'socket: [' . $errorcode . ']' . $errormsg . PHP_EOL;
        break;
    }
} while (strlen($reply) < $len);

echo 'Total Received: ' . strlen($reply) . PHP_EOL;

?>