使用 Ratchet Websockets 进行 PHP 实时聊天
Posted
技术标签:
【中文标题】使用 Ratchet Websockets 进行 PHP 实时聊天【英文标题】:PHP Real Time chat with Ratchet Websockets 【发布时间】:2016-05-02 20:53:47 【问题描述】:我是 php Websockets 的初学者,我正在尝试使用数据库存储创建实时聊天。我做得很好,但现在我遇到了一个问题。有问题,当 user1 向 user2 发送消息并且 user2 先到站点(在 localhoste 上先重新加载)时,它不会是“实时”的。
让我进一步解释一下。
这是我的 server.php。跟棘轮教程差不多:
$loop = React\EventLoop\Factory::create();
$pusher = new \Pusher();
$context = new React\ZMQ\Context($loop);
$pull = $context->getSocket(ZMQ::SOCKET_PULL);
$pull->bind('tcp://127.0.0.1:5555'); // Binding to 127.0.0.1 means the only client that can connect is itself
$pull->on('message', array($pusher, 'onBlogEntry'));
$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\Http\HttpServer(
new Ratchet\WebSocket\WsServer(
new Ratchet\Wamp\WampServer($pusher ))), $webSock);
$loop->run();
在 pusher.php 中最重要的是这些方法(我省略了其他不重要的东西):
protected $subscribedTopics = array();
protected $myID = array();
public function onSubscribe(ConnectionInterface $conn, $data)
$this->subscribedTopics[json_decode($data)->teamID] = $data;
$this->myID[json_decode($data)->userID] = $data;
public function onBlogEntry($entry)
$entryData = json_decode($entry, true);
if ((!array_key_exists($entryData['team_id'], $this->subscribedTopics)) ||
(!array_key_exists($entryData['to_user_id'], $this->myID))
)
return;
$teamID = $this->subscribedTopics[$entryData['team_id']];
$teamID->broadcast($entryData);
在我的 presenter Class 中,我的表单很简单。当用户提交此表单时,此代码如下:
$this->chatPartner = $values['to_user_id']; //this I get from the form
$this->redrawControl('msg'); //here I redraw my layout
$this->messages_model->addMessage($values); //here I send data to database
$context = new \ZMQContext();
$socket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'my pusher');
$socket->connect("tcp://localhost:5555");
$socket->send(json_encode($values));
然后,在 view 我有这个 javascript 代码:
var myJSON = ''
+ '"teamID" : $teamId,' //this I get from the presenter
+ '"userID" : $userId' //this I get from the presenter
+ '';
var conn = new ab.Session('ws://localhost:8080',
function()
conn.subscribe(myJSON, function(topic, data)
if (data.from_user_id == mypartnerIdA)
//here I edit the DOM
);
,
function()
console.warn('WebSocket connection closed');
,
'skipSubprotocolCheck': true
);
那么,回到我的问题。我模拟2个用户。 User1 重新加载此页面,javascript 连接首先在哪里。 User2 在他之后重新加载此页面。当 User1 向 user2 发送消息时,消息立即(实时)出现。但是当 user2 向 user1 发送消息时,该消息不会立即出现 - 它仅在下次重新加载页面后才会出现。
我的问题是 - 如何解决这个问题?如何使 user2 的消息也实时?如何修复我的代码?
【问题讨论】:
【参考方案1】:您可能对您最终订阅的数据有什么误解。 它旨在用于聊天会话的 ID。
例如:
A 与 B 聊天 (chatId = 1) B 与 C 聊天 (chatId = 2) C 与 A 聊天 (chatId = 3)A、B 和 C 在一个聊天中 (chatId = 4)
var chatId = 2; //this chat is only between users B and C
conn.subscribe( chatId , function(topic, data)
...
对我来说,理解它的最简单方法是将其与 twitter 上的主题标签进行比较。 在您的情况下,每个主题标签都是一个 chatId。 对于每个订阅主题标签/聊天 ID。您将拥有一个 WebSocket 连接,以便您接收它的所有更新。
从长远来看,这将是一种更简单的方法,然后为 userId 参数设置细分连接。 它还可以很容易地存储在数据库中,以便您知道将消息发送给谁以及不发送给谁。
【讨论】:
伙计,非常感谢你,我不相信有人在这里帮助我 :)) 没问题,如果您需要更多信息,请告诉我以上是关于使用 Ratchet Websockets 进行 PHP 实时聊天的主要内容,如果未能解决你的问题,请参考以下文章
如何在 MAMP 或 XAMPP 上安装 Ratchet WebSockets for PHP?
如何使实时服务器 Ratchet WebSockets 工作?
iis8 上 WSS 上的 Ratchet Websockets