我使用带 fgets 的 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->sendToAll($message); 通过 websocket 发送数据。
我不能一个接一个地放置 while 循环,因为它只会运行我放在第一个的循环,
while (true) { A() }; while (true) { B() };
B() 永远不会被调用我无法合并 while 循环,因为 websocket 会减慢 popen 的读取速度,反之亦然。
while (true) { A(); B();
如果 B 需要很长时间才能完成,A 的运行速度就会很慢。
遇到这种情况我该怎么办?我对线程、 fork 脚本之间的通信或其他任何概念持开放态度。
最佳答案
这是 Producer-Consumer
问题的经典场景。只是你有两个。您可以分解问题以更容易地理解它。
WebSocket Consumer:此代码将通过 WebSocket 发送数据。您可以将其视为一个单独的线程,其中数据从
Q1
(只是一个名称)出列并发送。WebSocket 生产者:一旦一些数据到达 WebSocket 入口,它就会被排入缓冲区。只是这和上面的不是同一个队列。我们将其命名为
Q2
。这也需要是一个单独的线程,一旦将数据排入队列并向适当的消费者发出信号,该线程就会进入休眠状态。HDD Consumer:此代码将执行与 WebSocket Consumer 相同的操作,唯一的区别是它将数据存储在硬盘上而不是 WebSocket 上。它将有自己的线程并与
Q2
一起工作。HDD Producer:我相信你能猜到这是做什么的。此代码将从硬盘读取数据并将其放入
Q1
队列。与所有生产者一样,它需要向消费者发出信号,通知他们队列中有新商品。
现在回到您的代码,PHP 不适合多线程编程,尽管 it's completely possible .这就是为什么你找不到那么多例子的原因。但如果您坚持,这里有您需要的东西:
PHP's Mutex class .此类将帮助您防止多个线程同时访问相同的数据。
调用
Signaling
的东西我在 PHP 中找不到!它被用来 告诉其他线程队列中的某些数据已准备好 consumer,或者说,会唤醒消费者线程 当它有事做的时候。
最后要说的是,在适当的多线程软件中,您不会使用sleep
函数来降低系统负载/防止系统崩溃。多线程编程就是关于线程之间的信号和对话。
关于php - 通过 websockets 发送 popen 的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32537950/