【发布时间】:2013-10-04 15:19:43
【问题描述】:
注意:这不与使用
MessageComponentInterface的this question 相同。我改用WampServerInterface,所以这个问题专门针对那个部分。我需要一个带有代码示例和解释的答案,因为我可以看到这对将来的其他人有帮助。
为单个用户尝试循环推送
我正在使用 Ratchet 和 ZeroMQ 的 WAMP 部分,我目前有一个工作版本的 push integration tutorial。
我正在尝试执行以下操作:
- zeromq 服务器已启动并运行,准备记录订阅者和取消订阅者
- 用户通过 websocket 协议在浏览器中进行连接
- 一个循环被启动,它将数据发送给请求它的特定用户
- 当用户断开连接时,该用户数据的循环将停止
我的第 (1) 和 (2) 点有效,但我遇到的问题是第三点:
首先:我怎样才能只向每个特定用户发送数据? 广播将其发送给每个人,除非“主题”最终可能是个人用户 ID?
其次:我有一个很大的安全问题。如果我要从客户端发送想要订阅的用户 ID,这似乎是我需要的,那么用户可以更改变量到另一个用户的 ID 并返回他们的数据。
第三点:我必须运行一个单独的 php 脚本,其中包含 zeromq 的代码以开始实际循环。我不确定这是最好的方法,我宁愿让它完全在代码库中工作,而不是单独的 php 文件。这是我需要整理的一个主要领域。
以下代码显示了我目前拥有的内容。
刚刚从控制台运行的服务器
我按字面意思输入php bin/push-server.php 来运行它。订阅和取消订阅将输出到此终端以进行调试。
$loop = React\EventLoop\Factory::create();
$pusher = Pusher;
$context = new React\ZMQ\Context($loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5555');
$pull->on('message', array($pusher, 'onMessage'));
$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
$webServer = new Ratchet\Server\IoServer(
new Ratchet\WebSocket\WsServer(
new Ratchet\Wamp\WampServer(
$pusher
)
),
$webSock
);
$loop->run();
通过 websocket 发送数据的 Pusher
我省略了无用的东西,专注于 onMessage() 和 onSubscribe() 方法。
public function onSubscribe(ConnectionInterface $conn, $topic)
{
$subject = $topic->getId();
$ip = $conn->remoteAddress;
if (!array_key_exists($subject, $this->subscribedTopics))
{
$this->subscribedTopics[$subject] = $topic;
}
$this->clients[] = $conn->resourceId;
echo sprintf("New Connection: %s" . PHP_EOL, $conn->remoteAddress);
}
public function onMessage($entry) {
$entryData = json_decode($entry, true);
var_dump($entryData);
if (!array_key_exists($entryData['topic'], $this->subscribedTopics)) {
return;
}
$topic = $this->subscribedTopics[$entryData['topic']];
// This sends out everything to multiple users, not what I want!!
// I can't send() to individual connections from here I don't think :S
$topic->broadcast($entryData);
}
开始循环使用上述 Pusher 代码的脚本
这是我的问题 - 这是一个单独的 php 文件,希望将来可以集成到其他代码中,但目前我不确定如何正确使用它。我是否从会话中获取用户 ID?我仍然需要从客户端发送它...
// Thought sessions might work here but they don't work for subscription
session_start();
$userId = $_SESSION['userId'];
$loop = React\EventLoop\Factory::create();
$context = new ZMQContext();
$socket = $context->getSocket(ZMQ::SOCKET_PUSH, 'my pusher');
$socket->connect("tcp://localhost:5555");
$i = 0;
$loop->addPeriodicTimer(4, function() use ($socket, $loop, $userId, &$i) {
$entryData = array(
'topic' => 'subscriptionTopicHere',
'userId' => $userId
);
$i++;
// So it doesn't go on infinitely if run from browser
if ($i >= 3)
{
$loop->stop();
}
// Send stuff to the queue
$socket->send(json_encode($entryData));
});
最后是要订阅的客户端js
$(document).ready(function() {
var conn = new ab.Session(
'ws://localhost:8080'
, function() {
conn.subscribe('topicHere', function(topic, data) {
console.log(topic);
console.log(data);
});
}
, function() {
console.warn('WebSocket connection closed');
}
, {
'skipSubprotocolCheck': true
}
);
});
结论
以上是可行的,但我真的需要弄清楚以下几点:
如何向个人用户发送个人消息?当他们访问在 JS 中启动 websocket 连接的页面时,我是否也应该启动将内容推入 PHP 队列的脚本(zeromq)?这就是我目前正在手动执行的操作,只是感觉不对。
从 JS 订阅用户时,从会话中获取用户 ID 并从客户端发送它是不安全的。这可能是伪造的。请告诉我有一个更简单的方法,如果是,如何?
【问题讨论】:
标签: php websocket zeromq ratchet reactphp