Подтвердить что ты не робот

Отправить вывод popen через websockets

Я использую popen с fgets для асинхронного чтения вывода tcpdump.

Код ниже должен быть запущен в командной строке, а не с 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 с помощью $websocket- > sendToAll ($ message);

  • Я не могу поместить циклы while один за другим, потому что он будет запускать только тот цикл, который я поставил первым, while (true) { A() }; while (true) { B() }; B() никогда не будет называться

  • Я не могу объединить циклы while, потому что веб-узлы замедляют чтение popen и наоборот. while (true) { A(); B(); }, если B занимает много времени, A будет медленно запускаться.

Что я могу сделать в этой ситуации? Я открыт для идеи потоков, связи между разветвленными скриптами или чем-то еще.

4b9b3361

Ответ 1

Это классический сценарий для проблемы Producer-Consumer. Просто у вас их двое. Вы можете решить проблему, чтобы понять ее легче.

  • WebSocket Consumer. Этот код отправит данные через WebSocket. Вы можете рассматривать это отдельный поток, в котором данные удаляются из Q1 (только имя) и отправляются.

  • Производитель WebSocket. Когда некоторые данные поступают в Gate WebSocket, они помещаются в буфер. Это просто, что это не та же очередь, что и выше. Назовите его Q2. Это также должен быть отдельный поток, и этот поток переходит в спящий режим, как только он выдает данные и сигнализирует соответствующему потребителю.

  • Жесткий потребитель. Этот код будет делать то же самое, что и WebSocket Consumer, единственное отличие состоит в том, что он будет хранить данные на жестком диске вместо WebSocket. Он будет иметь свой собственный поток и работает с Q2.

  • Производитель HDD. Я уверен, что вы можете догадаться, что это делает. Этот код будет считывать данные с жесткого диска и помещать его в очередь Q1. Как и все производители, он должен сигнализировать своим потребителям, информируя их о новом элементе в очереди.

Теперь, возвращаясь к вашему коду, PHP не подходит для многопоточного программирования, даже если это полностью возможно. Вот почему вы не можете найти много примеров для этого. Но если вы настаиваете, вот что вам нужно:

  • PHP класс темы

  • класс PHP Mutex. Этот класс поможет вам предотвратить одновременный доступ к одним и тем же данным нескольким потокам.

  • Что-то вызывать Signaling, которое я не могу найти в PHP! Это использовано сообщить другим потокам, что некоторые данные в очереди готовы быть или, другими словами, он пробудит потребительский поток когда ему что-то нужно делать.

Заключительное слово состоит в том, что в правильном многопоточном программном обеспечении вы не будете использовать функцию sleep, чтобы снизить системную нагрузку/предотвратить сбой системы. Многопоточное программирование предназначено для сигнализации и разговора между потоками.

Ответ 2

Как насчет wscat? Следующая команда:

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

отправляет две строки ниже ws://echo.websocket.org.

hello
bye

Обратите внимание, что ^C в командной строке есть Control-C (не двухбуквенная комбинация ^ и C).