Я хочу написать веб-приложение 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) сделает клиентов независимыми по часовой стрелке, если вы хотите использовать блокирующие вызовы, тогда файлы на самом деле могут быть способом.