doupaimo8288 2014-01-16 12:42
浏览 203
已采纳

PHP WebSocket ZMQ - 聊天操作 - 将数据发送给特定用户

im working on a PHP project based on Symfony 2.2.11 and I installed the socketo related to the following tutorial http://socketo.me/docs/install to make my chat script working.

ServerCommand.php // Code of the command line that starts the WebSocket server

$oLoop = Factory::create();

    // Listen for the web server to make a ZeroMQ push after an ajax request
    $oContext = new Context($oLoop);
    $oPull = $oContext->getSocket(\ZMQ::SOCKET_PULL);
    // LET IT 127.0.0.1
    $oPull->bind('tcp://127.0.0.1:5555'); // Binding to 127.0.0.1 means the only client that can connect is itself
    $oPull->on('message', array($oChat, 'onMessage'));

    // Set up our WebSocket server for clients wanting real-time updates
    $oWebSock = new Server($oLoop);
    $oWebSock->listen(7979, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
    $webServer = new IoServer(
        new HttpServer(
            new WsServer(
                new WampServer(
                    $oChat
                )
            )
        ),
        $oWebSock
    );

    $oLoop->run();

After a message is being added to database : MessagesController.php

....
// This is our new stuff
        $oContext = new \ZMQContext();
        $oSocket = $oContext->getSocket(\ZMQ::SOCKET_PUSH, 'PushMe');
        $oSocket->connect("tcp://mydomain:5555");

        $aData = array(
            'topic'         => 'message',
            'sUsername'     => $oUserCurrent->getUsername(),
            'sMessage'      => $sMessage
        );

        $oSocket->send(json_encode($aData));
.....

The chat service : Chat.php

/**
 * A lookup of all the topics clients have subscribed to
 */
public function onSubscribe(ConnectionInterface $conn, $topic) 
{
    // When a visitor subscribes to a topic link the Topic object in a  lookup array
    $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);

}

/**
 * @param string JSON'ified string we'll receive from ZeroMQ
 */
public function onMessage($jData) 
{
    $aData = json_decode($jData, true);

    var_dump($aData);

    if (!array_key_exists($aData['topic'], $this->subscribedTopics)) {
        return;
    }

    $topic = $this->subscribedTopics[$aData['topic']];

    // This sends out everything to multiple users, not what I want!!

    // re-send the data to all the clients subscribed to that category
    $topic->broadcast($aData);
}

JS code that receives data : messages.html.twig :

var conn = new ab.Session(
                    'ws://mydomain:7979' // The host (our Ratchet WebSocket server) to connect to
                  , function() {            // Once the connection has been established
                        conn.subscribe('message', function(topic, data) 
                        {
                            console.log(topic);
                            console.log(data);
                        });
                    }
                  , function() {            // When the connection is closed
                        console.warn('WebSocket connection closed');
                    }
                  , {                       // Additional parameters, we're ignoring the WAMP sub-protocol for older browsers
                        'skipSubprotocolCheck': true
                    }
                );

So everytings working perfectly, when I send a new Message, it goes to DB then it lands on the page of the chat.

PROBLEM : The data lands wherever the JS script is, and the result is that all users can get the same recorded message

ASKING : How can I make data lands in a specific user page ?

Thank you

展开全部

  • 写回答

1条回答 默认 最新

  • doutuoben6908 2014-01-16 14:02
    关注

    You are using Ratchet on backend side, right?

    So, here you have very good example of case you need:

    http://socketo.me/docs/hello-world

    You should keep your client connections inside $clients property (not collection of resources id!). So, you can choose one element from this collection and send a message only to this client.

    Example:

    public function onSubscribe(ConnectionInterface $conn, $topic) 
    {
        // When a visitor subscribes to a topic link the Topic object in a  lookup array
        $subject = $topic->getId();
        $ip = $conn->remoteAddress;
    
        if (!array_key_exists($subject, $this->subscribedTopics)) 
        {
            $this->subscribedTopics[$subject] = $topic;
        }
    
        $this->clients[] = $conn; // you add connection to the collection
    
        $conn->send("Hello new user!"); // you send a message only to this one user
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

悬赏问题

  • ¥20 求一个简易射频信号综测仪
  • ¥15 esp8266 tally灯 接收端改为发射端
  • ¥30 Labview代码调用access 数据库,相同代码其中一个调用不出来是为什么
  • ¥15 基于51单片机的交通灯系统,找改程序有点急
  • ¥15 java启动jar包后,运行过程中宕机
  • ¥15 进行LM运算过程中出现了无法识别的问题,具体问题如下图
  • ¥500 高有偿提问!求优化设计微信小程序
  • ¥15 matlab在安装时报错 无法找到入口 无法定位程序输入点
  • ¥15 Android Studio webview 的使用问题, 播放器横屏全屏
  • ¥15 删掉jdk后重新下载,Java web所需要的eclipse无法使用
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部