Добрый день. Я создал свой первый веб сокет как показано в примерах. Столкнулся с проблемой что вебсокет по сути однопоточный.. то есть если есть несколько клиентов ждущих ответа от сервера то они получает их по очереди, а не параллельно. Каким образом из Ratchet WebSockets for PHP можно получить многопоточный вебсокет, чтобы у каждого клиента мог обращаться к вебсокету не стоя в очереди. Спасибо
Код (Text): class API implements MessageComponentInterface { public function __construct() { } public function onOpen(ConnectionInterface $conn) { } public function onMessage(ConnectionInterface $from, $msg) { // store data in db // some analysis (take several seconds) // back answer to client //How to back answer to all client in parallel ?? } public function onClose(ConnectionInterface $conn) { } public function onError(ConnectionInterface $conn, \Exception $e) { } } никогда не работал с форком раньше. Вот пример кода, можно схематично изобразить как это должно выглядеть? спасибо
старт сценария определение "общего" массива данных открытие сокета уход в бесконечный "мастер"-цикл ожидание соединения прием соедиения форк если ненулевой идентификатор процесса - это мастер и далее к началу бесконечного цикла иначе это воркер и продолжаем работать с клиентом. определили "частный" массив данных туда-сюда с клиентом пообщались, закрыли клиентский сокет, отправили мастеру уведомление о своей смерти, стали зомби. вот так это схематично должно выглядеть. пожалуйста. Добавлено спустя 5 минут 26 секунд: ну как минимум пид у них будет разный поэтому увтерждение "совершенно идентичных" (читай тождественных) неверно в корне. к тому же у одного будет стек детей а у другого - сигнальный канал с родителем. то есть опять они нифига не идентичны. в общем автор тут погорячился.
Ratchet, он работает как мультиплексор. По-этому, да, любое блокирующее действие останавливает другие клиенты. Решения тут два - или, как сказали, форк. Но тут нужно эксперементировать как поведет себя умирающих PHP с открытыми соединениями... как бы он их не позакрывал. Второй вариант - разбираться, на что тратите время. Если вы общаетесь с базой данных, то переводить ее в асинхронный режим. Большинство драйверов в PHP уже это умеют. Добавлено спустя 3 минуты 33 секунды: Вы правда думаете, что на данном этапе объяснения теории данному человеку это уточнение ему что-то даст, кроме увеличения количества букв и потока ненужной ему пока информации? Вам поменьше нужно умничать. Побольше с людьми общаться.
Долгая обработка запроса от клиента у меня как раз связана с тем что сервер ждет не появится ли определеная запись в базе данных в течение 5 секунд(например) от другого клиента . Если она есть сразу возвращает ответ клиент, если нет то ждет. Я так понимаю что если бы база данных могла асинхроно возвращать ответ то это решило бы мою проблему с многопоточностью , можно было бы обойтись и одним потоком... Это сложно организовать?
Вам видимо нужно это читать http://socketo.me/docs/push Это более правильно, чем дергать в цикле базу, даже если удастся это сделать асинхронно.
Сделал как вы сказали, все работает. Теперь такая проблема возникла.. Когда я закрываю терминал (ssh сессию), вебсокет закрывается. Каким образом можно заставить его постоянно работать. И как посмотреть из терминала запущен ли он, чтобы снова запустить его при надобности? Спасибо
А что в поиске забанили? Трудно поискать: как сделать чтобы программа работалата после выхода из терминала
ну дык у вас же не даемон а просто скрипт который живет в консольке. консольку прихлопнули - скрипт умер. всё банально. даемону дать пид-файл. по крону или другим даемоном проверять этот пид-файл. если он перешел в другое состояние - признаем умершим, трём мусор, пробуем заново запустить. и обязательно обучить даемона всем сигналам системы.
И еще такой вопрос. Код (Text): public function onMessage(ConnectionInterface $from, $msg) { $pid = pcntl_fork(); if ($pid == -1) { $this->myPrint("cant create fork"); } else if ($pid) { } else { // ..... $result $from->send($result); // $pid = getmypid(); // exit($pid); } } Если я закрываю дочерний процесс то клиент не получает сообщения... Если их не закрывать то все работает но процессы плодяться пробовал закрывать так: Код (Text): function _exit() { posix_kill(posix_getpid(), SIGTERM); } результат то же ок, даемон для меня новое слово , пошел изучать. (я вообще для мобильных устройств программирую, но появилось надобность серверную часть написать) upd: http://mithrandir.ru/professional/php/php-daemons.html благодаре этой статье с демонами разобрался.
так себе статья. надо искать где сигналы реализованы. дочка умирая становится зомби и отправляет сигнал родителю. родитель по алярму читает очередь сигналов, отпевает-хоронит-поминает своих детей, ублажает вышестоящий процесс, если сигнал от него. и так далее. написать программу которая по запросу к апачу будет выполнена в пхп-машине - это одно. а написать программу которая будет долго жить в системе - совсем другое. нужно за памятью следить, за потоками, за сигналами, за блокировками. ну и тут как бы еще такой момент как выбор языка. да, пхп конечно быстрее получается в плане написания кода. но для веба, где запрос пришел-ушел. для демонизации скорость деплоя должна играть роль меньшую нежели производительность эффективного алгоритма (это того который запрос обрабатывает а не спит часами).
Ganzal, Спасибо за помощь! А по проблеме отправки сообщения сокетом из дочернего процесса, перед смертью его можете что то посоветовать? Если закрываю процесс сообщение не отправляется...
1. клиент( на javascript) подключается к вебсокету. 2. затем посылает сообщение вебсокету - json в виде строки. 3. вебсокет получает сообщение от клиент,делает форк, в дочернем процессе, лезет в базу данных, и возвращает тоже - json в виде строки. 4. закрываем дочерней процесс сразу после отправки собшения клиенту. Если не делаю 4 этап то все работает, если закрываю дочерней процесс сообщение не отправляется. Хотя закрытие в коде после отправки.
есть мастер который слушает входящий сокет. пришел запрос от клиента у которого есть исходящий сокет. мастер форкнулся и готов обслуживать новый запрос на входящем сокете. ВСЁ с мастером. форк. принял подключение клиента и открыв клиентский входящий сокет и установив пир-ту-пир соединение между двумя сокетами - клиентским исходящим и своим клиентским входящим. чтение-запись-чтение-запись-итд-итп. закрыли клиентский входящий сокет (клиент на своей стороне считает соединение завершенным и закрывает свой исходящий сокет) и после этого уже ничего никуда не отправится. поэтому просто умираем. если у вас сообщения не ходят то в каком-то месте вы нарушаете логику работы сокетов. Добавлено спустя 3 минуты 32 секунды: там еще будут смешные плюшки типа пула подключений, ага. типа чтоб ваши чат-клиенты не задудосили сервак - нужно лимитировать кол-во одновременных форков.