Php 直通管理订阅
我尝试通过Throuway建立一个websocket服务器,它可以管理多个组。类似于聊天应用程序,其中每个客户端可以同时订阅一个或多个客户端,并向整个聊天室广播消息。我用一个古老版本的棘轮做到了这一点,但由于它运行不太平稳,我想切换到Throuway。遗憾的是,我找不到任何管理团队的方法。到目前为止,由于websocket管理器和客户端正在使用当前版本的Autobahn | js(18.x),我有以下内容 是否有人知道是否可以使用以下内容管理订阅组Php 直通管理订阅,php,websocket,autobahn,phpwebsocket,thruway,Php,Websocket,Autobahn,Phpwebsocket,Thruway,我尝试通过Throuway建立一个websocket服务器,它可以管理多个组。类似于聊天应用程序,其中每个客户端可以同时订阅一个或多个客户端,并向整个聊天室广播消息。我用一个古老版本的棘轮做到了这一点,但由于它运行不太平稳,我想切换到Throuway。遗憾的是,我找不到任何管理团队的方法。到目前为止,由于websocket管理器和客户端正在使用当前版本的Autobahn | js(18.x),我有以下内容 是否有人知道是否可以使用以下内容管理订阅组 <?php require_once
<?php
require_once __DIR__.'/../vendor/autoload.php';
use Thruway\Peer\Router;
use Thruway\Transport\RatchetTransportProvider;
$router = new Router();
$router->addTransportProvider(new RatchetTransportProvider("0.0.0.0", 9090));
$router->start();
有了直通车,情况与旧棘轮略有不同。首先,Throuway不是WAMP服务器。它只是一个路由器。因此,它没有像旧RathSet那样的服务器实例,可以让您包装所有服务器端功能。但它将只获取消息包,并根据订阅情况将它们路由到同一领域中的其他会话。如果您曾经使用过socket.io,那么realmidea类似于不同的连接,因此您可以将会话或连接限制为单个名称空间,或者分割不同套接字实例(如管理、访问者等)的功能
在autobahn(最新版本)的客户端,一旦您订阅了一个主题,然后在该主题中发布,Throuway将自动检测主题订阅者,并在同一领域向他们发送消息。但在旧的ratchet中,您需要通过保留一组可用频道来手动处理此问题,并在用户订阅时向每个频道添加用户,以及通过迭代向主题中的这些用户广播消息。这真的很痛苦
若您想在服务器端使用RPC调用,但不想在客户端包含一些内容,那个么仍然可以在服务器端使用名为internalClient的类。从概念上讲,内部客户端是另一个连接到Throuway客户端的会话,它在内部处理某些功能,而不公开其他客户端。它接收消息包并在其中执行操作,然后将结果返回给请求的客户端连接。我花了一段时间才明白它是如何工作的,但一旦我明白了背后的想法就更有意义了
所以用一点点代码来更好地解释
在您的路由器实例中,您需要添加一个模块(注意,在voxys/Throuway包中,示例对于内部客户机几乎没有什么混淆)
server.php
require __DIR__ . "/../bootstrap.php";
require __DIR__ . '/InternalClient.php';
$port = 8080;
$output->writeln([
sprintf('Starting Sockets Service on Port [%s]', $port),
]);
$router = new Router();
$router->registerModule(new RatchetTransportProvider("127.0.0.1", $port)); // use 0.0.0.0 if you want to expose outside world
// common realm ( realm1 )
$router->registerModule(
new InternalClient() // instantiate the Socket class now
);
// administration realm (administration)
// $router->registerModule(new \AdminClient());
$router->start();
这将初始化直通路由器,并将internalclient实例连接到它。现在,在InternalClient.php文件中,您将能够访问实际路由以及当前连接的客户端。在他们提供的示例中,路由器不是实例的一部分,所以您只能使用新连接的会话id属性
InternalClient.php
require __DIR__ . "/../bootstrap.php";
require __DIR__ . '/InternalClient.php';
$port = 8080;
$output->writeln([
sprintf('Starting Sockets Service on Port [%s]', $port),
]);
$router = new Router();
$router->registerModule(new RatchetTransportProvider("127.0.0.1", $port)); // use 0.0.0.0 if you want to expose outside world
// common realm ( realm1 )
$router->registerModule(
new InternalClient() // instantiate the Socket class now
);
// administration realm (administration)
// $router->registerModule(new \AdminClient());
$router->start();
<?php
use Thruway\Module\RouterModuleInterface;
use Thruway\Peer\Client;
use Thruway\Peer\Router;
use Thruway\Peer\RouterInterface;
use Thruway\Logging\Logger;
use React\EventLoop\LoopInterface;
class InternalClient extends Client implements RouterModuleInterface
{
protected $_router;
/**
* Contructor
*/
public function __construct()
{
parent::__construct("realm1");
}
/**
* @param RouterInterface $router
* @param LoopInterface $loop
*/
public function initModule(RouterInterface $router, LoopInterface $loop)
{
$this->_router = $router;
$this->setLoop($loop);
$this->_router->addInternalClient($this);
}
/**
* @param \Thruway\ClientSession $session
* @param \Thruway\Transport\TransportInterface $transport
*/
public function onSessionStart($session, $transport)
{
// TODO: now that the session has started, setup the stuff
echo "--------------- Hello from InternalClient ------------\n";
$session->register('com.example.getphpversion', [$this, 'getPhpVersion']);
$session->subscribe('wamp.metaevent.session.on_join', [$this, 'onSessionJoin']);
$session->subscribe('wamp.metaevent.session.on_leave', [$this, 'onSessionLeave']);
}
/**
* Handle on new session joined.
* This is where session is initially created and client is connected to socket server
*
* @param array $args
* @param array $kwArgs
* @param array $options
* @return void
*/
public function onSessionJoin($args, $kwArgs, $options) {
$sessionId = $args && $args[0];
$connectedClientSession = $this->_router->getSessionBySessionId($sessionId);
Logger::debug($this, 'Client '. $sessionId. ' connected');
}
/**
* Handle on session left.
*
* @param array $args
* @param array $kwArgs
* @param array $options
* @return void
*/
public function onSessionLeave($args, $kwArgs, $options) {
$sessionId = $args && $args[0];
Logger::debug($this, 'Client '. $sessionId. ' left');
// Below won't work because once this event is triggered, client session is already ended
// and cleared from router. If you need to access closed session, you may need to implement
// a cache service such as Redis to access data manually.
//$connectedClientSession = $this->_router->getSessionBySessionId($sessionId);
}
/**
* RPC Call messages
* These methods will run internally when it is called from another client.
*/
private function getPhpVersion() {
// You can emit or broadcast another message in this case
$this->emitMessage('com.example.commonTopic', 'phpVersion', array('msg'=> phpVersion()));
$this->broadcastMessage('com.example.anotherTopic', 'phpVersionRequested', array('msg'=> phpVersion()));
// and return result of your rpc call back to requester
return [phpversion()];
}
/**
* @return Router
*/
public function getRouter()
{
return $this->_router;
}
/**
* @param $topic
* @param $eventName
* @param $msg
* @param null $exclude
*/
protected function broadcastMessage($topic, $eventName, $msg)
{
$this->emitMessage($topic, $eventName, $msg, false);
}
/**
* @param $topic
* @param $eventName
* @param $msg
* @param null $exclude
*/
protected function emitMessage($topic, $eventName, $msg, $exclude = true)
{
$this->session->publish($topic, array($eventName), array('data' => $msg), array('exclude_me' => $exclude));
}
}
有了直通车,情况与旧棘轮略有不同。首先,Throuway不是WAMP服务器。它只是一个路由器。因此,它没有像旧RathSet那样的服务器实例,可以让您包装所有服务器端功能。但它将只获取消息包,并根据订阅情况将它们路由到同一领域中的其他会话。如果您曾经使用过socket.io,那么realmidea类似于不同的连接,因此您可以将会话或连接限制为单个名称空间,或者分割不同套接字实例(如管理、访问者等)的功能
在autobahn(最新版本)的客户端,一旦您订阅了一个主题,然后在该主题中发布,Throuway将自动检测主题订阅者,并在同一领域向他们发送消息。但在旧的ratchet中,您需要通过保留一组可用频道来手动处理此问题,并在用户订阅时向每个频道添加用户,以及通过迭代向主题中的这些用户广播消息。这真的很痛苦
若您想在服务器端使用RPC调用,但不想在客户端包含一些内容,那个么仍然可以在服务器端使用名为internalClient的类。从概念上讲,内部客户端是另一个连接到Throuway客户端的会话,它在内部处理某些功能,而不公开其他客户端。它接收消息包并在其中执行操作,然后将结果返回给请求的客户端连接。我花了一段时间才明白它是如何工作的,但一旦我明白了背后的想法就更有意义了
所以用一点点代码来更好地解释
在您的路由器实例中,您需要添加一个模块(注意,在voxys/Throuway包中,示例对于内部客户机几乎没有什么混淆)
server.php
require __DIR__ . "/../bootstrap.php";
require __DIR__ . '/InternalClient.php';
$port = 8080;
$output->writeln([
sprintf('Starting Sockets Service on Port [%s]', $port),
]);
$router = new Router();
$router->registerModule(new RatchetTransportProvider("127.0.0.1", $port)); // use 0.0.0.0 if you want to expose outside world
// common realm ( realm1 )
$router->registerModule(
new InternalClient() // instantiate the Socket class now
);
// administration realm (administration)
// $router->registerModule(new \AdminClient());
$router->start();
这将初始化直通路由器,并将internalclient实例连接到它。现在,在InternalClient.php文件中,您将能够访问实际路由以及当前连接的客户端。在他们提供的示例中,路由器不是实例的一部分,所以您只能使用新连接的会话id属性
InternalClient.php
require __DIR__ . "/../bootstrap.php";
require __DIR__ . '/InternalClient.php';
$port = 8080;
$output->writeln([
sprintf('Starting Sockets Service on Port [%s]', $port),
]);
$router = new Router();
$router->registerModule(new RatchetTransportProvider("127.0.0.1", $port)); // use 0.0.0.0 if you want to expose outside world
// common realm ( realm1 )
$router->registerModule(
new InternalClient() // instantiate the Socket class now
);
// administration realm (administration)
// $router->registerModule(new \AdminClient());
$router->start();
<?php
use Thruway\Module\RouterModuleInterface;
use Thruway\Peer\Client;
use Thruway\Peer\Router;
use Thruway\Peer\RouterInterface;
use Thruway\Logging\Logger;
use React\EventLoop\LoopInterface;
class InternalClient extends Client implements RouterModuleInterface
{
protected $_router;
/**
* Contructor
*/
public function __construct()
{
parent::__construct("realm1");
}
/**
* @param RouterInterface $router
* @param LoopInterface $loop
*/
public function initModule(RouterInterface $router, LoopInterface $loop)
{
$this->_router = $router;
$this->setLoop($loop);
$this->_router->addInternalClient($this);
}
/**
* @param \Thruway\ClientSession $session
* @param \Thruway\Transport\TransportInterface $transport
*/
public function onSessionStart($session, $transport)
{
// TODO: now that the session has started, setup the stuff
echo "--------------- Hello from InternalClient ------------\n";
$session->register('com.example.getphpversion', [$this, 'getPhpVersion']);
$session->subscribe('wamp.metaevent.session.on_join', [$this, 'onSessionJoin']);
$session->subscribe('wamp.metaevent.session.on_leave', [$this, 'onSessionLeave']);
}
/**
* Handle on new session joined.
* This is where session is initially created and client is connected to socket server
*
* @param array $args
* @param array $kwArgs
* @param array $options
* @return void
*/
public function onSessionJoin($args, $kwArgs, $options) {
$sessionId = $args && $args[0];
$connectedClientSession = $this->_router->getSessionBySessionId($sessionId);
Logger::debug($this, 'Client '. $sessionId. ' connected');
}
/**
* Handle on session left.
*
* @param array $args
* @param array $kwArgs
* @param array $options
* @return void
*/
public function onSessionLeave($args, $kwArgs, $options) {
$sessionId = $args && $args[0];
Logger::debug($this, 'Client '. $sessionId. ' left');
// Below won't work because once this event is triggered, client session is already ended
// and cleared from router. If you need to access closed session, you may need to implement
// a cache service such as Redis to access data manually.
//$connectedClientSession = $this->_router->getSessionBySessionId($sessionId);
}
/**
* RPC Call messages
* These methods will run internally when it is called from another client.
*/
private function getPhpVersion() {
// You can emit or broadcast another message in this case
$this->emitMessage('com.example.commonTopic', 'phpVersion', array('msg'=> phpVersion()));
$this->broadcastMessage('com.example.anotherTopic', 'phpVersionRequested', array('msg'=> phpVersion()));
// and return result of your rpc call back to requester
return [phpversion()];
}
/**
* @return Router
*/
public function getRouter()
{
return $this->_router;
}
/**
* @param $topic
* @param $eventName
* @param $msg
* @param null $exclude
*/
protected function broadcastMessage($topic, $eventName, $msg)
{
$this->emitMessage($topic, $eventName, $msg, false);
}
/**
* @param $topic
* @param $eventName
* @param $msg
* @param null $exclude
*/
protected function emitMessage($topic, $eventName, $msg, $exclude = true)
{
$this->session->publish($topic, array($eventName), array('data' => $msg), array('exclude_me' => $exclude));
}
}
如果您希望您的客户端只监听推送通知,但无法发布任何消息,因为您希望使用ZMQ在服务器端发布消息,那么如何关闭客户端的连接?如果客户端试图发布消息,我基本上希望强制关闭WebSocket连接,因为我希望消息通过AJAX发送,然后通过ZMQ发送到WebSocket连接。然后WebSocket连接将消息传播/广播到所有连接的客户端。您应该能够添加一个onMessage侦听器,并且不返回任何内容,基本上不返回任何内容。所以,当客户端尝试发送消息时,什么也不会发生。由于消息传递是WebSocket的核心,如果您不能在客户端代码上管理它,我认为除了吞咽或根本不倾听之外,您没有什么可以做的