使用Ratchet Websockets进行PHP实时聊天


PHP Real Time chat with Ratchet Websockets

我是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);   
}

在我的演示者类中,我有一个简单的表单。当用户提交此表单时,代码如下:

$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));

然后,在视图中,我有以下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}
    );

那么,回到我的问题。我模拟了两个用户。User1重新加载此页面,其中首先是javascript连接。User2在他之后重新加载此页面。当用户1向用户2发送消息时,消息立即出现(实时)。但当user2向user1发送消息时,该消息不会立即出现——它只会在下次重新加载页面后出现。

我的问题是-如何解决这个问题?如何使user2的消息也是实时的?我该如何修复我的代码?

您可能对最终要订阅的数据有误解。它用于聊天会话的ID。

例如:

  • A与B聊天(聊天ID=1)
  • B与C聊天(聊天ID=2)
  • C与a聊天(聊天ID=3)
  • A、 B和C在一次聊天中(聊天ID=4)

    var chatId = 2; //this chat is only between users B and C
    conn.subscribe( chatId , function(topic, data) {
        ...
    }
    

对我来说,理解它最简单的方法是将它与推特上的标签进行比较。在您的情况下,每个标签都是一个聊天ID。每个订阅一个标签/聊天ID。你将有一个WebSocket连接,这样你就可以接收到它的所有更新。

从长远来看,这将是一种更容易做到这一点的方法,然后通过为userId参数细分连接。它也可以很容易地存储在数据库中,这样你就知道该向谁发送消息,不向谁发送。