Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send output of popen through websockets

Tags:

php

websocket

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.

like image 518
Dave Chen Avatar asked Sep 12 '15 10:09

Dave Chen


2 Answers

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.

like image 145
Mehran Avatar answered Oct 03 '22 22:10

Mehran


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).

like image 23
Takahiko Kawasaki Avatar answered Oct 03 '22 23:10

Takahiko Kawasaki