Лучшая практика для нескольких методов подписки в React / Ratchet / ZMQ

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

Для этого сценария я использую сокет ZMQ PUSH в моем UserController, когда пользователь входит или выходит из системы.

UserConstroller

public function login() {

//... here is the auth code, model call etc...

$aUserData = array();// user data comes from the database with username, logintime, etc....

$context = new \ZMQContext();
$oSocket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'USER_LOGIN_PUSHER'); // use persistent_id
if($oSocket instanceof \ZMQSocket) {

$oSocket->connect("tcp://127.0.0.1:5555"); //
$oSocket->send(json_encode($aUserData));
}
}

public function logout() {
//... here is the logout code, model call etc ....

$aUserData = array();// user data comes from the SESSION with username, logintime, etc....

$context = new \ZMQContext();
$oSocket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'USER_LOGOUT_PUSHER'); // use persistent_id
if($oSocket instanceof \ZMQSocket) {

$oSocket->connect("tcp://127.0.0.1:5555"); //
$oSocket->send(json_encode($aUserData));
}
}

Тогда у меня есть класс Pusher, как в документах Ratchet: ссылка на сайт

В этом классе есть два метода: onUserLogin а также onUserLogout и, конечно, все остальные вещи, как

onSubscribe, onOpen, onPublish

UserInformationPusher

 public function onUserLogin($aUserData) {
//var_dump("onUserLogin");
$sUserData = json_decode($aUserData, true);

$oTopic = $this->subscribedTopics["user_login"];

if($oTopic instanceof Topic) {
$oTopic->broadcast($sUserData);
} else {
return;
}
}

public function onUserLogout($aUserData) {
//var_dump("onUserLogout");
$entryData = json_decode($aUserData, true);

$oTopic = $this->subscribedTopics["user_logout"];

if($oTopic instanceof Topic) {
$oTopic->broadcast($entryData);
} else {
return;
}
}

Последняя часть — это WampServer / WsServer / HttpServer с Loop, который прослушивает входящие соединения. Есть также моя розетка ZMQ PULL

RatchetServerConsole

public function start_server() {

$oPusher = new UserInformationPusher();

$oLoop = \React\EventLoop\Factory::create();
$oZMQContext = new \React\ZMQ\Context($oLoop);
$oPullSocket = $oZMQContext->getSocket(\ZMQ::SOCKET_PULL);

$oPullSocket->bind('tcp://127.0.0.1:5555'); // Binding to 127.0.0.1 means the only client that can connect is itself
$oPullSocket->on('message', array($oPusher, 'onUserLogin'));
$oPullSocket->on('message', array($oPusher, 'onUserLogout'));$oMemcache = new \Memcache();
$oMemcache->connect('127.0.0.1', 11211);
$oMemcacheHandler = new Handler\MemcacheSessionHandler($oMemcache);

$oSession = new SessionProvider(
new \Ratchet\Wamp\WampServer(
$oPusher
),
$oMemcacheHandler
);

//$this->Output->info("Server start initiation with memcache!...");
$webSock = new \React\Socket\Server($oLoop);
$webSock->listen(8080, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
$oServer = new \Ratchet\Server\IoServer(
new \Ratchet\Http\HttpServer(
new \Ratchet\WebSocket\WsServer(
$oSession
)
),
$webSock
);
$this->Output->info("Server started ");
$oLoop->run();

}

В этом примере вызов из login () или logout () всегда будет вызывать оба метода (onUserLogin и onUserLogout).
Я не смог найти некоторые документы, которые описывают, какие события я могу использовать в on ($ event, вызываемый $ listener) метод, у кого-нибудь есть ссылка / база знаний?
Как лучше всего проверить, какой метод из UserController был запущен?

  • Я мог бы добавить некоторую информацию к $ sUserData в контроллере и проверить это в Pusher
  • Я мог бы привязать другой сокет к другому порту (например, 5554 для PULL и PUSH) и использовать метод on () на этом
  • Я мог бы … есть другая лучшая практика, чтобы решить это?

Код клиента не нужен, потому что он работает нормально

3

Решение

В вашем RatchetServerConsole,

Удалить,

$oPullSocket->on('message', array($oPusher, 'onUserLogin'));
$oPullSocket->on('message', array($oPusher, 'onUserLogout'));

Добавлять,

$oPullSocket->on('message', array($oPusher, 'onUserActionBroadcast'));

.

В вашем UserInformationPusher,

Удалите onUserLogin () и onUserLogout ().

Добавлять,

public function onUserActionBroadcast($aUserData)
{
$entryData = json_decode($aUserData, true);

// If the lookup topic object isn't set there is no one to publish to
if (!array_key_exists($entryData['topic'], $this->subscribedTopics)) {
return;
}

$topic = $this->subscribedTopics[$entryData['topic']];

unset($entryData['topic']);

// re-send the data to all the clients subscribed to that category
$topic->broadcast($entryData);
}

.

Ваш UserConstroller (добавьте тему в $ aUserData),

public function login() {

//... here is the auth code, model call etc...

$aUserData = array();// user data comes from the database with username, logintime, etc....

$aUserData['topic'] = 'USER_LOGIN'; // add the topic name

$context = new \ZMQContext();
$oSocket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'my pusher'); // use persistent_id
if($oSocket instanceof \ZMQSocket) {

$oSocket->connect("tcp://127.0.0.1:5555"); //
$oSocket->send(json_encode($aUserData));
}
}

public function logout() {
//... here is the logout code, model call etc ....

$aUserData = array();// user data comes from the SESSION with username, logintime, etc....

$aUserData['topic'] = 'USER_LOGOUT'; // add the topic name

$context = new \ZMQContext();
$oSocket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'my pusher'); // use persistent_id
if($oSocket instanceof \ZMQSocket) {

$oSocket->connect("tcp://127.0.0.1:5555"); //
$oSocket->send(json_encode($aUserData));
}
}

.

Наконец в вашем просмотреть файл,

<script>
var conn = new ab.Session('ws://yourdomain.dev:9000', // Add the correct domain and port here
function() {
conn.subscribe('USER_LOGIN', function(topic, data) {
console.log(topic);
console.log(data);
});

conn.subscribe('USER_LOGOUT', function(topic, data) {
console.log(topic);
console.log(data);
});
},
function() {
console.warn('WebSocket connection closed');
},
{'skipSubprotocolCheck': true}
);
</script>

.

НОТА: Основная идея заключалась в том, чтобы использовать одну функцию широковещания в классе толкача.

4

Другие решения

После месяца интенсивной работы с лучшей практикой PHP в веб-сокетах я перешел от своего подхода к Crossbar.io, voryx / Thruway в бэкэнде PHP и Автобан | JS в интерфейсе.
Все эти компоненты поддерживают WAMP V2 Websocket Standard и способны справиться с моими требованиями.

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

3

По вопросам рекламы [email protected]