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) {line 下定义一个缓冲区大小,但你猜它失败了。我不知道如何正确处理它。

提前致谢。

4

1 回答 1

4

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

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

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

必须做三件事:

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

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

于 2016-04-20T15:31:49.743 回答