Send output of popen through websockets

一曲冷凌霜 提交于 2021-02-08 12:17:58

问题


I'm using popen with fgets to read the output of tcpdump asynchronously.

The below code should be run in the command line, not with apache and viewing it in your browser.

$handle = popen('tcpdump -nnX', 'r');

while (true) {
    $output = fgets($handle);
    print $output . "\n";
}

The problem arises when I try to output this information via websockets.

Websockets also use an infinite loop (for managing its sockets, ticks, and messages).

It looks something like:

while (true) {
    @socket_select($read,$write,$except,1);
    foreach ($read as $socket) {
        if ($socket == $this->master) {
            $client = socket_accept($socket);
...

I send data through the websocket with $websocket->sendToAll($message);.

  • I can't put the while loops one after the other because it will only run whichever loop I put first, while (true) { A() }; while (true) { B() }; B() will never be called

  • I can't merge the while loops, because the websockets slows down the reading of popen, and vise versa. while (true) { A(); B(); } if B is taking a long time to finish, A will be slow to run.

What can I do in this situation? I'm open to the idea of threads, communication between forked scripts, or anything else.


回答1:


This is the classic scenario for Producer-Consumer problem. It's just that you've got two of them. You can break down the problem to understand it easier.

  • WebSocket Consumer: This code will send data through WebSocket. You can consider this a separate thread in which data is dequeued from Q1 (just a name) and sent.

  • WebSocket Producer: Once some data arrives at at the WebSocket gate, it is enqueued into a buffer. It's just that this is not the same queue as above. Let's name it Q2. This needs to be a separate thread as well, and this thread goes to sleep once it enqueues the data and signals the appropriate consumer.

  • HDD Consumer: This code will do the same as WebSocket Consumer, the only difference is that it will store the data on a hard disk instead of WebSocket. It will have its own thread and works with Q2.

  • HDD Producer: I'm sure you can guess what this does. This code will read data off the hard disk and put it in Q1 queue. Like all the producers it needs to signal its consumers informing them of a new item in queue.

Now getting back to your code, PHP is not suitable for multi-thread programming even though it's completely possible. That's why you can not find that many examples for it. But if you insist, here are what you'll need:

  1. PHP's Thread class

  2. PHP's Mutex class. This class will help you prevent multiple threads to access the same data at the same time.

  3. Something call Signaling which I can not find in PHP! It is used to tell other threads that some data in queue is ready to be consumed, or in other words, it will wake up the consumer thread when it has something to do.

Final word is that in a proper multi thread software you won't be using sleep function to lower system's load / preventing system crash. Multi-thread programming is all about signaling and conversation between threads.




回答2:


How about wscat? The following command line:

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

sends the two lines below to ws://echo.websocket.org.

hello
bye

Note that ^C in the command line is a Control-C (not a two-letter combination of ^ and C).



来源:https://stackoverflow.com/questions/32537950/send-output-of-popen-through-websockets

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!