通过 websockets 发送 popen 的输出

2022-08-30 23:43:02

我正在使用带有fges的popen来异步读取tcpdump的输出。

以下代码应该在命令行中运行,而不是在apache中运行并在浏览器中查看它。

$handle = popen('tcpdump -nnX', 'r');

while (true) {
    $output = fgets($handle);
    print $output . "\n";
}

当我尝试通过websockets输出此信息时,问题就出现了。

Websockets还使用无限循环(用于管理其套接字,价格变动和消息)。

它看起来像这样:

while (true) {
    @socket_select($read,$write,$except,1);
    foreach ($read as $socket) {
        if ($socket == $this->master) {
            $client = socket_accept($socket);
...

我通过 websocket 发送数据,$websocket->发送到所有($message);。

  • 我不能把 while 循环一个接一个地放,因为它只会运行我放在第一个循环中的任何一个,B() 永远不会被调用while (true) { A() }; while (true) { B() };

  • 我无法合并 while 循环,因为 websockets 会减慢 popen 的读取速度,反之亦然。 如果B需要很长时间才能完成,A将运行缓慢。while (true) { A(); B(); }

在这种情况下我该怎么办?我对线程,分叉脚本之间的通信或其他任何东西的想法持开放态度。


答案 1

这是问题的经典场景。只是你有两个。您可以分解问题以更轻松地理解它。Producer-Consumer

  • WebSocket Consumer:此代码将通过 WebSocket 发送数据。您可以将其视为一个单独的线程,其中数据从(只是一个名称)中取消排队并发送。Q1

  • WebSocket Producer:一旦一些数据到达WebSocket门,它就会排队进入缓冲区。只是这与上面的队列不同。让我们给它起个名字。这也需要是一个单独的线程,一旦它排队数据并向适当的使用者发出信号,这个线程就会进入休眠状态。Q2

  • HDD Consumer:此代码将执行与WebSocket Consumer相同的操作,唯一的区别是它将数据存储在硬盘上而不是WebSocket上。它将有自己的线程,并与 .Q2

  • HDD制作人:我相信你可以猜到这是做什么的。此代码将从硬盘读取数据并将其放入队列中。像所有生产者一样,它需要向消费者发出信号,通知他们队列中有一个新项目。Q1

现在回到你的代码,PHP不适合多线程编程,即使它是完全可能的。这就是为什么你找不到那么多的例子。但是,如果您坚持,以下是您需要的:

  1. PHP 的线程类

  2. PHP 的互斥体类。此类将帮助您防止多个线程同时访问相同的数据。

  3. 在PHP中找不到的调用!它用于告诉其他线程队列中的某些数据已准备好被使用,或者换句话说,当它有事情要做时,它将唤醒使用者线程。Signaling

最后一句话是,在适当的多线程软件中,您将不会使用功能来降低系统的负载/防止系统崩溃。多线程编程就是关于线程之间的信令和对话。sleep


答案 2

wscat怎么样?以下命令行:

$ printf "hello\\nbye\\n^C" | wscat -c ws://echo.websocket.org

将下面的两行发送到 。ws://echo.websocket.org

hello
bye

请注意,命令行中的是 Control-C(不是 和 的两个字母组合)。^C^C


推荐