Как использовать именованные каналы в PHP между различными функциями или даже разными процессами без fork?

Я хочу написать веб-приложение Ajax, для конкретной игры. Два веб-клиента должны общаться друг с другом через сервер PHP. Мой подход к решению этого вопроса – использовать Ajax между клиентом и сервером, сервером и клиентом. Каждый клиент создает отдельный серверный процесс с использованием Ajax. Я хочу, чтобы эти два серверных процесса взаимодействовали через MySQL и через именованные каналы. Мне нужны именованные каналы, чтобы получить немедленный ответ для всего приложения.

Я не могу использовать один серверный процесс, который сначала создает канал, а затем вилки в два процесса, которые используют канал. Веб-приложения создают серверные процессы, когда веб-браузер отправляет запрос. Итак, мне нужны именованные каналы, где каждый процесс не знает больше имени файла именованного канала. Они не могут обмениваться файловыми дескрипторами (по крайней мере, я не знаю, как).

Моя проблема в том, что именованные каналы в PHP-режиме действительно работают до тех пор, пока они используются в одной и той же функции:

public function writeAndReadPipe_test(){ $pipeA = fopen("testpipe",'r+'); fwrite($pipeA, 'ABCD'); $pipeB = fopen("testpipe",'r+'); $content = fread($pipeB, 4); echo "[" . $content . "]<br>\n"; } public function testingPipes_same_function(){ posix_mkfifo("testpipe", 0777); $this->writeAndReadPipe_test(); } 

Но, когда я использую разные функции, команда fread($pipeB, 4) блокирует все приложение:

 public function writePipe_test(){ $pipeA = fopen("testpipe",'r+'); fwrite($pipeA, 'ABCD'); } public function readPipe_test(){ $pipeB = fopen("testpipe",'r+'); $content = fread($pipeB, 4); echo "[" . $content . "]<br>\n"; } public function testingPipes_different_functions(){ posix_mkfifo("testpipe", 0777); $this->writePipe_test(); $this->readPipe_test(); } 

Кто-нибудь знает, почему? И что я могу сделать, чтобы он работал между различными функциями на первом шаге? На втором этапе он должен работать даже между разными процессами! Я узнал, что у меня также возникает проблема, когда автор закрывает трубку, прежде чем читатель прочитает ее. Я полагаю, что функция закрывает ее автоматически, когда она заканчивается, но это только предположение.

Если PHP-путь не работает, я планирую позволить PHP открывать командную строку, генерировать команды BASH и выполнять их. Это должно работать в любом случае, пока мой веб-сервер работает в среде LAMP. Недостатком является то, что он не будет работать в средах WAMP.

Итак, есть ли у кого-нибудь какие-то идеи?

PS: Мне нужно блокировать каналы, чтобы позволить читателю подождать, пока не будет отправлено событие. Я знаю, что трубы могут работать в неблокирующем режиме, используя

 stream_set_blocking($pipe,false); 

или так, но вся идея заключается в том, чтобы делать это без опроса, используя только трубку, которая пробуждает читателя, как только происходит событие.

    Когда вы используете трубы в отдельных функциях, подобных этому, труба записи A, кажется, снова закрывается / отбрасывается (локальная область $ pipeA). Предполагалось, что труба должна быть открыта для чтения и / или записи, чтобы сохранить любую информацию, что действительно имеет смысл. Хотя я не знаю внутренней магии.

    Вы также можете заметить, что ваш блокирующий вызов чтения преуспевает, когда вы кормите канал из другого процесса (например, echo magic >> testpipe). Таким образом, у вас уже будет сделанный шаг 2, но вам нужно некоторое управление pipehandle.

    Если вы измените его следующим образом, это сработает:

      private $pipeA; public function writePipe_test(){ $this->pipeA = fopen("testpipe",'r+'); fwrite($this->pipeA, 'ABCD'); } 

    Изменить: или установить $ pipeA на глобальную область, если на то пошло ..

    Просто короткое заявление, что на самом деле я нашел хорошее решение с использованием именованных каналов:

     public function createPipe_test(){ posix_mkfifo("testpipe", 0777); } public function writePipe_test($value){ $pipeA = fopen("testpipe",'w'); $valueString = number_format($value); $valueLen = number_format(strlen($valueString)); fwrite($pipeA, $valueLen); fwrite($pipeA, $valueString); } public function readPipe_test(){ $pipeB = fopen("testpipe",'r'); $valueLen = fread($pipeB, 1); return fread($pipeB, $valueLen); } 

    У меня два процесса.

    Если процесс 1 вызывает writePipe_test (), он ожидает, пока процесс 2 вызовет readPipe_test (), чтобы прочитать данные из трубы.

    Если процесс 1 вызывает readPipe_test (), он ждет, пока процесс 2 вызовет writePipe_test (), чтобы что-то записать в трубу.

    Трюк – 'w' и 'r' вместо 'r +'.

    Я не уверен, что я понимаю ваш второй пост.

    Но прокомментировать последний, если я не пойму неправильно, TCP может быть еще сложнее, потому что вам нужно будет установить соединение, прежде чем вы сможете читать или писать, так что у вас есть разные накладные расходы

    Что касается закрытия pipehandle на конце функции, я предполагаю, что вы столкнетесь с той же проблемой с сокетами; но файл pipe остается!

    Постоянное хранилище (файлы, db) сделает клиентов независимыми по часовой стрелке, если вы хотите использовать блокирующие вызовы, тогда файлы на самом деле могут быть способом.