异步套接字客户端缓冲区大小

时间:2016-04-09 05:49:45

标签: php sockets asynchronous asyncsocket reactphp

我必须连接具有异步套接字连接的远程服务器并检索数据。我可以连接,但有一个问题。

包裹是按件发送的。我有两个选择;我可以设置缓冲区并将整个包装整合在一起,或者在完成所有传输后组合碎片。我认为第一个选项(缓冲物)是正确的方法。

我定义了一个缓冲区大小,但它在第一部分不起作用。在其他部分,它的工作原理,但使用这种方法,我不能将整个包装整体,因为第一部分限制为5,24 Kb。

您可以在下面找到我的代码:

$loop = React\EventLoop\Factory::create();

        $dnsResolverFactory = new React\Dns\Resolver\Factory();
        $dns = $dnsResolverFactory->createCached('8.8.8.8', $loop);
        $connector = new React\SocketClient\Connector($loop, $dns);
        $connector->create( ENDPOINT_IP , ENDPOINT_PORT )->then(function (React\Stream\Stream $stream) use ($loop) {

            $command = '{C:"EL",bmId:43,inst:"my_instance",tok:"my_token"}';

            $command_length = strlen($command);
            $command_length = pack("N", $command_length);

            $stream->write($command_length);
            $stream->write($command);

            $stream->bufferSize = 999999;
            $stream->on('data', function ($data) {

            $package    =   substr($data, 0, 4);
            $unpack     =   unpack('N', $package); // I'm getting whole package size

            echo $data;



            });


        });

        $loop->run();

我尝试在$stream->on('data', function ($data) {行下定义一个缓冲区大小,但你猜它失败了。我不知道如何正确处理它。

提前致谢。

1 个答案:

答案 0 :(得分:4)

“我可以设置一个缓冲区并将整个包装整合在一起,或者在完成所有传输后组合碎片。我认为第一个选项(缓冲物)是正确的方法。”

第一个选项是,只是因为它不是套接字通信的工作方式。

如果您正在接收5 kB数据,并且您将缓冲区设置得足够大,那么假设10 kB,您不能指望在$stream->on('data', function ($data) { ...的一次调用中您将获得全部5 kB。

必须做三件事:

  • 您需要知道在一个消息块中接收的数据的确切大小。您知道该消息将始终具有固定和已知大小,或者数据块具有可从中读取消息长度的标头。在您的情况下,您正在从接收数据的前4个字节中读取消息大小。
  • 在循环中,您需要读取来自服务器的数据块并连接它们,直到您有足够的字节来读取整个消息的大小。在你的情况下,这是4个字节。无论听起来多么奇怪,在两次调用$stream->on('data', function ($data) { ...时,有可能在两个块中收到1个然后3个字节。当连接数据的大小为>=4时,则会读取消息的大小。
  • 在同一个循环中,您需要继续读取来自套接字的数据块并将它们连接起来,直到您收到所有消息字节为止。当然,这意味着您需要在循环外定义一个存储接收数据的变量。收到整条消息后,您需要退出循环。

好主意是你为循环设置了一个计时器,这样你就可以等待在有限的时间内收到整个消息。可能发生客户端和服务器之间的连接在传输过程中被破坏,如果您没有超时逻辑,您的循环将永远等待接收整个消息。