2015-09-12 95 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兩個字母的組合)。