我使用popen和fgets异步读取tcpdump的输出。
下面的代码应该在命令行中运行,而不是使用apache并在浏览器中查看
$handle = popen('tcpdump -nnX', 'r');
while (true) {
$output = fgets($handle);
print $output . "n";
}
当我试图通过websocket输出这些信息时,问题就出现了。
Websockets还使用一个无限循环(用于管理其套接字、记号和消息(。
它看起来像:
while (true) {
@socket_select($read,$write,$except,1);
foreach ($read as $socket) {
if ($socket == $this->master) {
$client = socket_accept($socket);
...
我使用$websocket->sendToAll($message(;通过websocket发送数据;。
我不能把while循环一个接一个地放,因为它只会运行我先放的那个循环,
while (true) { A() }; while (true) { B() };
B((永远不会被称为我无法合并while循环,因为websocket会减慢popen的读取速度,反之亦然。
while (true) { A(); B(); }
如果B需要很长时间才能完成,则a的运行速度会很慢。
在这种情况下我该怎么办?我对线程、分叉脚本之间的通信或其他任何东西持开放态度。
这是Producer-Consumer
问题的经典场景。只是你有两个。你可以把这个问题分解,使它更容易理解。
-
WebSocket使用者:此代码将通过WebSocket发送数据。您可以将其视为一个单独的线程,在该线程中,数据从
Q1
(只是一个名称(出队并发送。 -
WebSocket Producer:一旦一些数据到达WebSocket门,就会将其排入缓冲区。只是这与上面的队列不同。让我们把它命名为
Q2
。这也需要是一个单独的线程,一旦将数据排入队列并向适当的使用者发出信号,该线程就会进入睡眠状态。 -
HDD消费者:此代码将与WebSocket消费者执行相同的操作,唯一的区别是它将数据存储在硬盘上,而不是WebSocket。它将有自己的线程,并与
Q2
一起工作。 -
HDD生产商:我相信你能猜到这是怎么回事。此代码将从硬盘上读取数据并将其放入
Q1
队列中。和所有生产商一样,它需要向消费者发出信号,告知他们队列中有新商品。
现在回到您的代码,PHP不适合多线程编程,尽管这是完全可能的。这就是为什么你找不到那么多例子。但如果你坚持,以下是你需要的:
-
PHP的线程类
-
PHP的Mutex类。此类将帮助您防止多个线程同时访问同一数据。
-
有一个叫
Signaling
的东西,我在PHP中找不到!它已被使用告诉其他线程队列中的某些数据已准备就绪消费,或者换句话说,它将唤醒消费者线程当它有事的时候。
最后一句话是,在一个合适的多线程软件中,你不会使用sleep
函数来降低系统负载/防止系统崩溃。多线程编程就是线程之间的信号和对话。
wscat怎么样?以下命令行:
$ printf "hello\nbye\n^C" | wscat -c ws://echo.websocket.org
将下面的两条线路发送到CCD_ 10。
hello
bye
注意,命令行中的^C
是Control-C(不是^
和C
的两个字母的组合(。