我正在使用popen和fgets来异步读取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循环,因为websockets减慢了popen的读取速度,反之亦然。 while (true) { A(); B(); }
如果B需要很长时间才能完成,A的运行速度会很慢。
在这种情况下我该怎么办?我对线程,分叉脚本之间的通信或其他任何东西的想法持开放态度。
答案 0 :(得分:7)
这是Producer-Consumer
问题的经典场景。只是你有两个。您可以分解问题以更容易理解。
WebSocket Consumer :此代码将通过WebSocket发送数据。您可以将此视为一个单独的线程,其中数据从Q1
(只是一个名称)出列并发送。
WebSocket Producer :一旦某些数据到达WebSocket门,它就会被排入缓冲区。只是这与上面的队列不同。我们将它命名为Q2
。这也需要是一个单独的线程,一旦它将数据排入队列并向适当的消费者发出信号,该线程就会进入休眠状态。
HDD Consumer :此代码与WebSocket Consumer相同,唯一的区别是它会将数据存储在硬盘而不是WebSocket上。它将拥有自己的主题并与Q2
一起使用。
硬盘生产商:我相信你能猜到这是做什么的。此代码将从硬盘读取数据并将其放入Q1
队列。与所有生产商一样,它需要向消费者发出信号通知他们队列中的新项目。
现在回到你的代码,即使it's completely possible,PHP也不适合多线程编程。这就是为什么你找不到那么多的例子。但如果你坚持,这就是你需要的:
PHP's Mutex class。此类将帮助您防止多个线程同时访问相同的数据。
在PHP中找不到我无法找到的Signaling
!它被使用了
告诉其他线程队列中的某些数据已准备就绪
消耗,或换句话说,它将唤醒消费者线程
当它有事可做时。
最后一句话是,在适当的多线程软件中,您将不会使用sleep
函数来降低系统的负载/防止系统崩溃。多线程编程就是线程之间的信令和对话。
答案 1 :(得分:2)
wscat怎么样?以下命令行:
$ printf "hello\\nbye\\n^C" | wscat -c ws://echo.websocket.org
将以下两行发送到ws://echo.websocket.org
。
hello
bye
请注意,命令行中的^C
是Control-C(不是^
和C
的双字母组合。)