2015-09-12 56 views
17

我正在用fgets使用popen异步读取tcpdump的输出。通过websockets发送popen输出

下面的代码应该在命令行中运行,而不是使用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($消息)WebSocket的发送数据;.

  • 我不能把while循环,一个接一个,因为它将只运行我把取环第一,while (true) { A() }; while (true) { B() }; B()将永远不会被称为

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

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

+0

不酷,崩溃我的浏览器,并使浏览器发疯,发出警告>。< –

+0

@IndigoIdentity新增。我的问题只关注cli,这里没有涉及浏览器。 (除了使用websockets进行查看,但这里省略的代码) –

+0

好吧,这部分是我自己的错,因为我之前在IP套接字上输入IP并输出到浏览器中,所以我已经将这种思想融入了我的心中。现在想一想,PHP中的异步套接字连接将会非常棒。很好的问题! –

回答

7

这是Producer-Consumer问题的经典场景。只是你有两个。你可以打破这个问题来更容易理解它。

  • 的WebSocket消费者:此代码将通过WebSocket的发送数据。你可以考虑将这个数据从Q1(仅仅是一个名字)中取出并发送出去。

  • WebSocket Producer:一旦某些数据到达WebSocket门,它就会被排入缓冲区。只是这不是上面的队列。我们将其命名为Q2。这需要成为一个独立的线程,并且一旦它将数据排入队列并向适当的消费者发出信号,该线程就会进入休眠状态。

  • HDD消费者:此代码与WebSocket使用者一样,唯一的区别是它将数据存储在硬盘而不是WebSocket上。它将有自己的线程并与Q2一起工作。

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

现在又回到了你的代码,PHP不适合多线程编程,即使it's completely possible。这就是为什么你不能找到它的很多例子。但是,如果你坚持,这里有你需要的东西:

  1. PHP's Thread class

  2. PHP's Mutex class。该类将帮助您防止多个线程同时访问相同的数据。

  3. 东西叫Signaling,我无法在PHP中找到!它被用于 告诉其他线程队列中的某些数据已准备好被使用,或者换句话说,它将在需要时唤醒消费者线程 。

最后一句话是,在一个适当的多线程软件,你将不会被使用sleep功能,降低系统的负载/防止系统崩溃。多线程编程完全是关于线程之间的信号传输和对话。

+0

PHP中的POSIX信号:https://secure.php.net/manual/en/function .pcntl-signal.php - 这定义了一个信号处理程序。 – Ghedipunk

+0

@Ghedipunk谢谢,但我认为这些功能是为了进程间通信而不是线程间的。由于我们正在讨论多线程,整个脚本将在一个进程内,因此使用PCNTL函数挂起一个线程应暂停进程中的所有线程。我必须承认我自己没有尝试过,这是我相信的。 – Mehran

+0

好点,我还没有在多线程环境中尝试过它。至少,这是玩的东西。我不得不承认,我个人避免使用多线程来支持分叉。 – Ghedipunk

2

wscat怎么样?以下命令行:

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

将以下两行发送到ws://echo.websocket.org

hello 
bye 

注意,在命令行^C是控制-C(不是^C两个字母的组合)。