ReactPHP套接字服务器:什么触发写入(到客户端)?

时间:2014-03-26 18:05:58

标签: php sockets reactphp

当尝试写入客户端时,消息会被缓冲,在某些情况下,它根本就没有被写入。

当前状态:
当我远程登录到服务器时,Server Ready:消息很容易按预期打印。

当我发送随机数据(“关闭”除外)时,服务器的终端每秒都很好地显示进度,但是客户端输出会等到所有睡眠后,然后立即打印出来。

最重要的是,当发送“关闭”时,它只是等待强制性的第二个,然后在客户端没有任何写出的情况下关闭。

目标:
我的主要目标是在关闭连接之前将快速消息写入客户端。

CODE:

// server.php
$loop = React\EventLoop\Factory::create();

$socket = new React\Socket\Server($loop);
$socket->on('connection', function ($conn)
{
    $conn->write("Server ready:\n");

    $conn->on('data', function ($data) use ($conn)
    {
        $data = trim($data);

        if( $data == 'close')
        {
            $conn->write("Bye\n");
            sleep(1);
            $conn->close();
        }

        for ($i = 1; $i<5; $i++) {
            $conn->write(". ");
            echo '. '; 
            sleep(1);
        }

        $conn->write(".\n");
        echo ".\n";

        $conn->write("You said \"".$data."\"\n");

    });
});
$socket->listen(1337, '127.0.0.1');
$loop->run();

概要
为什么我不能在关闭前给客户写任何东西?

1 个答案:

答案 0 :(得分:6)

您遇到的问题是因为您忘记了驱动ReactPHP的事件循环。我最近在构建服务器时遇到了这个问题,在遵循代码后,我发现了两件可以帮助你解决问题的事情。

  1. 如果在写入后关闭连接,它只会在写入之前关闭连接。解决这个问题可以帮助您解决下一个问题...正确的调用将内容写入客户端,然后关闭连接称为$conn->end('msg');如果您遵循此代码链,行为就会变得清晰;首先它基本上写入连接,就像你运行$conn->write('msg');但是它为full-drain事件注册一个新的事件处理程序,这个处理程序简单地调用$conn->close();;仅在写缓冲区完全清空时才调度full-drain事件。所以你可以看到end的使用,只需在关闭连接之前等待写入。
  2. drainfull-drain仅在写入流后调度。写缓冲区完全为空时发生full-drain。在写缓冲区清空超过其drain后调度softLimit,默认情况下为{20}字节。

    1. 您的写入没有通过的原因是因为$conn->write('msg')只将字符串添加到写缓冲区;它实际上并没有写。事件循环需要在给定时间写入之前运行。您对sleep()的使用不正确,因为这会阻止该行的调用。作为反应,你不想阻止任何代码执行。如果您完成了一项任务,那么让您的函数返回,代码执行返回到反应主事件循环。如果您希望在某些时间间隔内运行,或者只是在循环的下一次迭代中运行,则可以使用$loop->addTimer($seconds, $callback)$loop->addPeriodicTimer($seconds, $callback),{{1}为主事件循环安排回调}或$loop->nextTick($callback)
    2. 最终,这是因为你在编程而没有承认我们仍然处于阻塞线程中。你的代码阻塞,阻止整个反应事件循环,反过来阻止所有反应为你做的事情。将处理时间放回循环以确保它可以执行排队的读/写操作。您只需要循环迭代就可以使写缓冲区开始清空(取决于缓冲区的大小,它可能会也可能不会全部写出来)

      如果您的目标只是修复连接关闭位,请将您的通话切换为$loop->futureTick($callback),而不是写入 - &gt;关。但是我相信你打印圆点的另一个循环也不会像我认为你期望/希望它的工作方式那样。由于它的目的不是很明确,如果你能告诉我你的目标是什么,我也可以帮助你重组这一步骤。