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

7
我需要使用异步套接字连接远程服务器并检索数据。我可以成功连接,但是出现了问题。
数据包会分成几个部分发送。我有两个选择:我可以设置一个缓冲区并一次性获取整个数据包,或在传输完成后将这些部分组合起来。我认为第一种选项(缓冲区)是正确的方法。
我正在定义一个缓冲区大小,但在第一部分中它不起作用。在其他部分中,它可以正常工作,但使用这种方法我无法在一次操作中获得整个数据包,因为第一部分受到限制,最多只能传输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个回答

4

"我可以设置缓冲区并在一次性获取整个包或在传输完成后合并数据块。我认为第一种选项(缓冲区)是正确的方式。"

第一种选项不是正确的方式,因为这不是套接字通信的工作方式。

例如,如果您要接收5KB的数据,并且将缓冲区设置得足够大,比如10KB,您不能期望在调用$stream->on('data', function($data) { ...一次之后就能收到全部5KB的数据。

必须做三件事:

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

好的想法是为循环设置计时器,以便您可以等待限定时间内接收到整个消息。在传输期间,客户端和服务器之间的连接可能会中断,如果没有超时逻辑,则您的循环将永远等待接收到整个消息。


实际上,我尝试了很多方法,包括您的建议,但结果仍然相同。 - Deniz B.
嗯,您还没有说明您遇到了什么确切的问题。 请发布您收到的结果以及期望的结果。 如果您在一个响应中收到多个数据包,则需要有额外的逻辑。通常情况下,当一个数据包的所有数据都到达时,您将在同一响应中获得下一个数据包的一部分。您需要保存这些多余的数据,并在下一次迭代中将其用作起始数据。 - BJovke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接