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.
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:
PHP's Thread class
PHP's Mutex class. This class will help you prevent multiple threads to access the same data at the same time.
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.
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
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With