打开连接时将用户ID从浏览器发送到websocket服务器

打开连接时将用户ID从浏览器发送到websocket服务器,websocket,real-time,zeromq,ratchet,Websocket,Real Time,Zeromq,Ratchet,在问这个问题之前,我尽了最大努力阅读了《塞维尔》 关于SO的问题(标记为Ratchet和处理类似问题,但 没用。我甚至问了一个没有引起注意的问题,我 因此,删除它来写另一个(希望更多) 清楚) 我的最终目标是使用Ratchet构建一个一对一的私人聊天应用程序。除了我不能向特定用户发送消息之外,一切都正常 每个登录用户在访问网站的安全区域时都会连接到websocket服务器: $(document).ready(function() { var conn = new WebSocket

在问这个问题之前,我尽了最大努力阅读了《塞维尔》 关于SO的问题(标记为Ratchet和处理类似问题,但 没用。我甚至问了一个没有引起注意的问题,我 因此,删除它来写另一个(希望更多) 清楚)

我的最终目标是使用Ratchet构建一个一对一的私人聊天应用程序。除了我不能向特定用户发送消息之外,一切都正常

每个登录用户在访问网站的安全区域时都会连接到websocket服务器:

$(document).ready(function() { 

    var conn = new WebSocket('ws://localhost:8080');
        conn.onopen = function(e) {
            console.log("Connection established!");

            // Here I need to send the logged in user_id to websocket server
            // and get it in onOpen method so that I can index my array 
            // of connections with user_id instead of
            //$connection->ResourceId, I explain more below

        };

        conn.onmessage = function(e) {
            console.log(e.data);
        };

});
当用户在聊天盒中写入消息时,消息通过AJAX发送到web服务器,然后使用ZeroMQ推送到Websocket。在控制器中:

// Persistence of Message(message_id, sender_id, receiver_id, message_text)
                .....

                $context = new \ZMQContext();
                $socket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'my pusher');
                $socket->connect("tcp://localhost:5555");

                $pushData = array(
                       'receiver_id' => $receiver_id,
                       'sender_id'  => $user->getId(),
                       'message'  => $message->getMessageText(),
                    );
                $socket->send(json_encode($pushData));
所以最后,我的websocket服务器能够知道哪个是使用JSON的接收方id。但他如何知道哪个是该用户的连接呢?换句话说,我需要将websocket连接存储在一个由用户id索引的数组中

<?php
namespace RealTime;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Wamp\WampServerInterface;

class Pusher implements WampServerInterface, MessageComponentInterface{

    private $clients;

    public function onOpen(ConnectionInterface $conn) {

        $this->clients[$conn->resourceId] = $conn;
        // I need here to get the user_id received from browser while opening connection
    }

    public function onMessageEntry($entry) {
        $entryData = json_decode($entry, true);

        //This is not what I need (It sends to all users in array)
        foreach ($this->clients as $key => $client) {

        $client->send($entryData['message']); 
        }
    }
    public function onMessage(ConnectionInterface $from, $msg) {
        echo $msg; 
    }
}

问题:

  • 如何在打开连接时从客户端发送登录的
    用户id
    。我需要在websocket server中具有该值,以便我可以使用它索引我的客户端数组(
    $client[user\u id]=$conn
    而不是
    $client[resourceid]=$conn
    )。我尝试了javascript函数
    send
    ,但我不知道从哪里接收发送的数据(即使
    onMessage
    也没有打印任何内容)

  • 为什么
    onMessage
    方法甚至没有执行
    MessageComponentInterface
    实现(是因为我有
    onMessageEntry
    方法+
    $pull->on('message',array($pusher,'onMessageEntry'));
    代码行吗


  • 谢谢。

    这是我的发现,欢迎提出任何改进此解决方案的建议

    可以使用棘轮。这将需要使用一个Symfony自定义会话处理程序,如图所示。我在以下代码中使用
    PdoSessionHandler

    <?php
        require dirname(__DIR__) . '/vendor/autoload.php';
    
        use YourDirectory\Pusher;
        use Symfony\Component\HttpFoundation\Session\Storage\Handler;
    
        use \Ratchet\Session\SessionProvider;
    
        $pusher = new Pusher;
    
        $pdo = new PDO('mysql:host=localhost;dbname=community', 'root', null);
    
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
        //This info is related to you db
        $dbOptions = array(
            'db_table'      => 'session',
            'db_id_col'     => 'sess_id',
            'db_data_col'   => 'sess_data',
            'db_time_col'   => 'sess_time',);
    
            $loop   = \React\EventLoop\Factory::create();
            $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, 'onMessageEntry'));
    
            $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 SessionProvider(
                            new Ratchet\Wamp\WampServer(
                                $pusher
                            ),new Handler\PdoSessionHandler($pdo,$dbOptions)
                        )
                    )
                ),
                $webSock
            );
    
            $loop->run();
        ?>
    
    但在此之前,我已将用户id添加到Web服务器中的会话(在返回初始页面的控制器中)

    附言:

  • 移动到PdoSessionHandler可以通过实现(Symfony)来完成

  • 我仍然不能回答2,但是所有可以放在消息上的逻辑现在都被移动到了消息中心上,这暂时满足了需求


  • 作为在
    clientConnection
    和他的
    ID
    之间建立关联的另一种方法,您需要在打开与websocket服务器的连接后使用websocket发送消息。此消息将包含您的用户ID。您将使用它在数组中通过他的
    ID
    索引他的连接对象


    对于第二个问题,我知道默认的websocket实现不能正常工作,特别是在
    pubsub
    协议中,您需要使用websocket库,因此我建议使用它,它是一个很好的websocket库,具有许多奇妙的特性。

    实际上在我最后一次尝试时,我放弃了使用PHP websocket(这项工作太复杂了)并开始使用SocketIO和nodeJS,解决了我的整个问题,可以给我一个功能简单的聊天系统。

    感谢Anas的贡献。你的选择是我尝试的第一件事。我在使用
    send
    函数打开连接时使用了javascript,但我没有找到一种方法来获得推送中的值er类。您的解决方案是我真正想要的,因为我刚刚失败,所以使用了SessionProvider。在websocket服务器中从何处获取发送的id?\n您没有收到数据,因为web浏览器中websocket的默认实现无法与pubsub协议正常工作。请尝试将其与AuthObHnJS一起使用。它具有pubsu的实现b protocole.看看这个,我没有使用PDOSessionProvider,因为会话没有与连接对象相同的生命周期。看看这个,好的,我明白你的意思。我将尝试使用Authobanjs并给出反馈。感谢google groups链接感谢你与整个社区分享你的经验。
    <?php
        require dirname(__DIR__) . '/vendor/autoload.php';
    
        use YourDirectory\Pusher;
        use Symfony\Component\HttpFoundation\Session\Storage\Handler;
    
        use \Ratchet\Session\SessionProvider;
    
        $pusher = new Pusher;
    
        $pdo = new PDO('mysql:host=localhost;dbname=community', 'root', null);
    
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
        //This info is related to you db
        $dbOptions = array(
            'db_table'      => 'session',
            'db_id_col'     => 'sess_id',
            'db_data_col'   => 'sess_data',
            'db_time_col'   => 'sess_time',);
    
            $loop   = \React\EventLoop\Factory::create();
            $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, 'onMessageEntry'));
    
            $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 SessionProvider(
                            new Ratchet\Wamp\WampServer(
                                $pusher
                            ),new Handler\PdoSessionHandler($pdo,$dbOptions)
                        )
                    )
                ),
                $webSock
            );
    
            $loop->run();
        ?>
    
       public function onOpen(ConnectionInterface $conn) {  
            $this->clients[$conn->Session->get('current_user_id')] = $conn;
        }
    
    public function onMessageEntry($entry) {
    
                $entryData = json_decode($entry, true);
                $ReceiverConnection=$this->clients[$entryData['receiver_id']];
                $ReceiverConnection->send($entryData['message']);                  
            }
    
    $user = $this->getUser();
    $request->getSession()->set('current_user_id', $user->getId());