2017-02-07 11 views
5

Итак, я бегу Ratchet (PHP) WebSocket сервер с несколькими маршрутами, которые соединяют сделать несколько приложений с храповым механизмом (MessageComponentInterfaces):Отправка сообщения из PHP скрипт для нескольких приложений Ratchet WebSocket (через ZMQ гнездо)

//loop 
$loop = \React\EventLoop\Factory::create(); 

//websocket app 
$app = new Ratchet\App('ws://www.websocketserver.com', 8080, '0.0.0.0', $loop); 

/* 
* load routes 
*/ 
$routeOne = '/example/route'; 
$routeOneApp = new RouteOneApp(); 
$app->route($routeOne, $routeOneApp, array('*')); 

$routeTwo = '/another/route'; 
$routeTwoApp = new AnotherApp(); 
$app->route($routeTwo, $routeTwoApp, array('*')); 

Отсюда я связываю сокет ZMQ, чтобы получать сообщения, отправленные с php-скриптов, запущенных на обычном сервере Apache.

// Listen for the web server to make a ZeroMQ push after an ajax request 
$context = new \React\ZMQ\Context($loop); 
$pull = $context->getSocket(\ZMQ::SOCKET_PULL); 
$pull->bind('tcp://127.0.0.1:5050'); // Binding to 127.0.0.1 means the only client that can connect is itself 
$pull->on('message', array($routeOneApp, 'onServerMessage')); 

Наконец, сервер запущен:

//run 
$loop->run(); 

Это отлично работает до тех пор, как я связываю только один из храповых приложений к разъему ZMQ. Тем не менее, я хотел бы иметь возможность отдельно отправлять сообщения в оба приложения Ratchet. Для этой цели я подумал о связывании два ZMQ розетки к разным маршрутам нравятся:

$pullOne->bind('tcp://127.0.0.1:5050' . $routeOne); // Binding to 127.0.0.1 means the only client that can connect is itself 
$pullOne->on('message', array($routeOneApp, 'onServerMessage')); 

и

$pullTwo->bind('tcp://127.0.0.1:5050' . $routeTwo); // Binding to 127.0.0.1 means the only client that can connect is itself 
$pullTwo->on('message', array($routeTwoApp, 'onServerMessage')); 

Однако это приводит к сообщению об ошибке от ZMQ при связывании второго гнезда, говоря заданный адрес уже используется.

Вопрос в том, есть ли другой способ использования маршрутов через разъем ZMQ? Или я должен использовать другие средства для различения сообщений для отдельных приложений Ratchet, и если да, то что было бы хорошим решением? Я думал о привязке к двум различным портам, но понял, что это будет довольно уродливое решение ?!

+0

Вы уверены, что хотите связать(), когда в PULL? Обычно в ZMQ сторона PUSH связывается(), сторона PULL соединяет(). – Jack

+0

Хороший вопрос, я скопировал привязку из некоторого учебника, который я нашел в Интернете, и, похоже, он работает. Я посмотрю, работает ли функция connect(). –

ответ

2

В общем случае TCP-пакеты идентифицируются четырьмя кортежами (ip-адрес отправителя, порт отправителя, приемник ip, порт приемника).

Когда входящий пакет достигает сетевого уровня, он перенаправляется в соответствующее приложение, просматривая IP-адрес приемника и порт. Если вы используете одну и ту же пару для обоих приложений, для слоя будет невозможно решить, кому отправить его, когда приходит соединение.

Одним из решений было бы связать одно соединение и написать обычный обработчик который смотрит на входящий контент, а затем решает (я полагаю, у вас есть логика), чтобы различать входящие подключения к различным экземплярам и затем вызывает соответствующий обработчик. Обработчик может получить объект соединения и, следовательно, может обрабатывать соединение.

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

Редактировать: Я попытался ответить на вопрос независимо от типа приложения (Racket/ZMQ и т. Д.), Потому что проблема, которую вы пытаетесь решить, является фундаментальной, общей для любого сетевого приложения.

Для этого случая, поскольку у вас есть два приложения, которые работают и хотят прослушивать один и тот же порт, у вас может быть обычный обработчик, который может посмотреть URL-адрес запроса и перенаправить соединение с соответствующим обработчиком.

Запрос URL может быть получен с помощью

$querystring = $conn->WebSocket->request->getQuery(); 

Теперь клиенты могут подключаться с помощью

ws://localhost:5050/app1 
and 
ws://localhost:5050/app2 

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

+0

То, что меня спрашивает, это тот факт, что Ratchet использует несколько «приложений», которые связаны с одним и тем же портом. Очевидно, что все они подключаются к одному и тому же веб-узлу и отправляются с использованием идентификаторов или другой методологии. По правде говоря, было бы лучше написать собственный протокол JSON, который отправляет сообщения на основе AppID или что-то подобное, но похоже, что для этого уже существует метод, а плохая документация Ratchet не описывает его хорошо. – user1274820

+0

Как только вы скажете несколько «приложений», это означает, что вы говорите о прикладном уровне. Это синоним наличия нескольких модулей внутри http-сервера, такого как apache. Вам нужен ID (как вы упомянули), чтобы различать запросы к различным приложениям. В случае HTTP-сервера это делается по URL-адресу. Если документация Rachet не документирует это хорошо, было бы неплохо реализовать собственный протокол поверх соединения, предоставленного Rachet. –

+0

Вам не обязательно ехать в JSON. Помните, что соединения Websocket также запускаются как обычные HTTP-соединения. Таким образом, вы можете использовать URL для дифференциации. Вам нужно будет найти путь в документации, чтобы получить URL-адрес, используемый для установления связи с websocket. То есть, если Раше дает доступ к этому. –

 Смежные вопросы

  • Нет связанных вопросов^_^