3

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

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

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

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

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

代码:

// 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();

摘要:
为什么在关闭之前我无法向客户写入任何内容?

4

1 回答 1

8

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

  1. 如果在写入后关闭连接,它只会在写入之前关闭连接。解决这个问题可以帮助您解决下一个问题......正确调用向客户端写入内容,然后关闭连接$conn->end('msg');如果您遵循此代码链,则行为变得清晰;首先它基本上就像你运行一样写入连接,$conn->write('msg');但随后它为事件注册一个新的事件处理程序full-drain,这个处理程序简单调用$conn->close();; full-drain仅当写入缓冲区完全清空时才会调度该事件。所以你可以看到end的使用,只是在关闭连接之前等待写入。

drainand仅在full-drain写入流后才调度。full-drain当写缓冲区完全为空时发生。drain在写缓冲区被清空后调度softLimit,默认为 2048 字节。

  1. 您的写入未通过的原因是$conn->write('msg')仅将字符串添加到写入缓冲区;它实际上并没有写。事件循环需要在有时间写入之前运行。您对sleep()react 的使用不正确,因为这会阻止该行的呼叫。在反应中,您不想阻止任何代码执行。如果你完成了一项任务,那么让你的函数返回,代码执行返回到 react 主事件循环。如果您希望事情在特定的时间间隔内运行,或者只是在循环的下一次迭代中运行,您可以使用$loop->addTimer($seconds, $callback)、或$loop->addPeriodicTimer($seconds, $callback)$loop->nextTick($callback)$loop->futureTick($callback)

归根结底,这是因为您在编程时没有承认我们仍处于阻塞线程中。任何阻塞的代码都会阻塞整个反应事件循环,进而阻塞反应为您所做的一切。放弃处理时间回到循环,以确保它可以执行您已排队的读取/写入。您只需要在循环的迭代中发生写入缓冲区开始清空(取决于缓冲区的大小,它可能会或可能不会将其全部写出)

如果您的目标只是修复连接关闭位,请将您的调用切换到$conn->end('msg')而不是 write -> close。但是,我相信您打印点的另一个循环也不会以我认为您期望/希望它工作的方式运行。由于它的目的不是很明确,如果你能告诉我你的目标是什么,我也可以帮助你重组这一步。

于 2015-04-16T17:12:59.220 回答