[英]Best Practice for Multiple Subscribe Methods in React / Ratchet / ZMQ
I try to build a little realtime websocket use-case, where users can login and see all other users logged in, get notified when a new user signs in or an existing user logs out. 我尝试构建一个小的实时websocket用例,用户可以登录并查看登录的所有其他用户,在新用户登录或现有用户注销时收到通知。
For this scenario i use the ZMQ PUSH Socket in my UserController when a user logs in or logs out. 对于这种情况,当用户登录或注销时,我在UserController中使用ZMQ PUSH Socket。
UserConstroller 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));
}
}
Then i've got a Pusher class like in the Ratchet docs: link 然后我有一个像Ratchet文档中的Pusher类: 链接
In this class there are two methods: onUserLogin and onUserLogout and of course all the other stuff like 在这个类中有两个方法: onUserLogin和onUserLogout ,当然还有所有其他的东西
onSubscribe, onOpen, onPublish
onSubscribe,onOpen,onPublish
UserInformationPusher 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;
}
}
The last piece is the WampServer/WsServer/HttpServer with a Loop that listens to the incoming connections. 最后一部分是WampServer / WsServer / HttpServer,它有一个Loop来监听传入的连接。 There is also my ZMQ PULL socket
还有我的ZMQ PULL插座
RatchetServerConsole 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();
}
In this example, the call from login() or logout() would always call both methods(onUserLogin and onUserLogout). 在此示例中,来自login()或logout()的调用将始终调用这两个方法(onUserLogin和onUserLogout)。 I was not able to find some docs, which describe what events i can use in the on($event, callable $listener) method, does anyone have a link/knowledge base?
我无法找到一些文档,它描述了我可以在on($ event,callable $ listener)方法中使用哪些事件,是否有人拥有链接/知识库? What is the best approach to check which method from the UserController was fired?
检查UserController中哪个方法被触发的最佳方法是什么?
No Client code needed cause it works fine 没有客户端代码,因为它工作正常
In your RatchetServerConsole , 在你的RatchetServerConsole中 ,
Remove, 去掉,
$oPullSocket->on('message', array($oPusher, 'onUserLogin'));
$oPullSocket->on('message', array($oPusher, 'onUserLogout'));
Add, 加,
$oPullSocket->on('message', array($oPusher, 'onUserActionBroadcast'));
. 。
In your UserInformationPusher , 在UserInformationPusher中 ,
Remove onUserLogin() and onUserLogout(). 删除onUserLogin()和onUserLogout()。
Add, 加,
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);
}
. 。
Your UserConstroller (add the topic in $aUserData), 您的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));
}
}
. 。
Finally in your view file , 最后在你的视图文件中
<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>
. 。
NOTE : The basic idea was to use a single broadcast function in the pusher class. 注意 :基本思想是在推送器类中使用单个广播功能。
After one month of intensive handling with PHPs best practice in websockets i changed from my approach to the Crossbar.io , voryx/Thruway in the PHP Backend and Autobahn|JS in the Frontend. 经过一个月的密集处理,我在websockets的PHP最佳实践中改变了我的方法, 改进了PHP后端的Crossbar.io , voryx / Thruway和前端的Autobahn | JS 。 All of these componentes support the WAMP V2 Websocket Standard and are able to handle my requirements.
所有这些组件都支持WAMP V2 Websocket标准 ,并且能够满足我的要求。
If there are some requests i can post the solution to my problem above, with the usage of the mentioned components. 如果有一些请求我可以将解决方案发布到我上面的问题,并使用上述组件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.