3

ユーザーがログインして、ログインしている他のすべてのユーザーを表示し、新しいユーザーがサインインするか、既存のユーザーがログアウトしたときに通知を受け取ることができる、小さなリアルタイム Websocket ユースケースを構築しようとしています。

このシナリオでは、ユーザーがログインまたはログアウトするときに、UserController で ZMQ PUSH Socket を使用します。

ユーザーコントローラー

public function login() {

        //... here is the auth code, model call etc...

        $aUserData = array();// user data comes from the database with username, logintime, etc....

        $context = new \ZMQContext();
        $oSocket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'USER_LOGIN_PUSHER'); // use persistent_id
        if($oSocket instanceof \ZMQSocket) {

            $oSocket->connect("tcp://127.0.0.1:5555"); //
            $oSocket->send(json_encode($aUserData));
        }
    }

    public function logout() {
        //... here is the logout code, model call etc ....

        $aUserData = array();// user data comes from the SESSION with username, logintime, etc....

        $context = new \ZMQContext();
        $oSocket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'USER_LOGOUT_PUSHER'); // use persistent_id
        if($oSocket instanceof \ZMQSocket) {

            $oSocket->connect("tcp://127.0.0.1:5555"); //
            $oSocket->send(json_encode($aUserData));
        }
    }

次に、Ratchet docs のような Pusher クラスを取得しました:リンク

このクラスには 2 つのメソッドがあります: onUserLoginonUserLogoutです。

onSubscribe、onOpen、onPublish

ユーザー情報プッシャー

 public function onUserLogin($aUserData) {
        //var_dump("onUserLogin");
        $sUserData = json_decode($aUserData, true);

        $oTopic = $this->subscribedTopics["user_login"];

        if($oTopic instanceof Topic) {
            $oTopic->broadcast($sUserData);
        } else {
            return;
        }
    }

    public function onUserLogout($aUserData) {
        //var_dump("onUserLogout");
        $entryData = json_decode($aUserData, true);

        $oTopic = $this->subscribedTopics["user_logout"];

        if($oTopic instanceof Topic) {
            $oTopic->broadcast($entryData);
        } else {
            return;
        }
    }

最後の部分は、着信接続をリッスンするループを備えた WampServer/WsServer/HttpServer です。私のZMQ PULLソケットもあります

RatchetServerConsole

public function start_server() {

        $oPusher = new UserInformationPusher();

        $oLoop = \React\EventLoop\Factory::create();
        $oZMQContext = new \React\ZMQ\Context($oLoop);
        $oPullSocket = $oZMQContext->getSocket(\ZMQ::SOCKET_PULL);

        $oPullSocket->bind('tcp://127.0.0.1:5555'); // Binding to 127.0.0.1 means the only client that can connect is itself
        $oPullSocket->on('message', array($oPusher, 'onUserLogin'));
        $oPullSocket->on('message', array($oPusher, 'onUserLogout'));


        $oMemcache = new \Memcache();
        $oMemcache->connect('127.0.0.1', 11211);
        $oMemcacheHandler = new Handler\MemcacheSessionHandler($oMemcache);

        $oSession = new SessionProvider(
            new \Ratchet\Wamp\WampServer(
                $oPusher
            ),
            $oMemcacheHandler
        );

        //$this->Output->info("Server start initiation with memcache!...");
        $webSock = new \React\Socket\Server($oLoop);
        $webSock->listen(8080, '0.0.0.0'); // Binding to 0.0.0.0 means remotes can connect
        $oServer = new \Ratchet\Server\IoServer(
            new \Ratchet\Http\HttpServer(
                new \Ratchet\WebSocket\WsServer(
                    $oSession
                )
            ),
            $webSock
        );
        $this->Output->info("Server started ");
        $oLoop->run();

    }

この例では、login() または logout() からの呼び出しは、常に両方のメソッド (onUserLogin と onUserLogout) を呼び出します。on($event, callable $listener)メソッドで使用できるイベントを説明しているドキュメントを見つけることができませんでした。リンク/知識ベースを持っている人はいますか? UserController のどのメソッドが起動されたかを確認する最善の方法は何ですか?

  • Controller の $sUserData に情報を追加し、Pusher でこれを確認できます。
  • 他のソケットを別のポート (PULL および PUSH の場合は 5554 など) にバインドし、このポートで on() メソッドを使用できます。
  • 私は...これを解決するための別のベストプラクティスはありますか?

正常に動作するため、クライアントコードは必要ありません

4

2 に答える 2

4

RatchetServerConsole

削除する、

$oPullSocket->on('message', array($oPusher, 'onUserLogin'));
$oPullSocket->on('message', array($oPusher, 'onUserLogout'));

追加、

$oPullSocket->on('message', array($oPusher, 'onUserActionBroadcast'));

.

UserInformationPusherで、

onUserLogin() と onUserLogout() を削除します。

追加、

public function onUserActionBroadcast($aUserData)
{
    $entryData = json_decode($aUserData, true);

    // If the lookup topic object isn't set there is no one to publish to
    if (!array_key_exists($entryData['topic'], $this->subscribedTopics)) {
        return;
    }

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

    unset($entryData['topic']);

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

.

UserConstroller ($ aUserDataにトピックを追加)、

public function login() {

    //... here is the auth code, model call etc...

    $aUserData = array();// user data comes from the database with username, logintime, etc....

    $aUserData['topic'] = 'USER_LOGIN'; // add the topic name

    $context = new \ZMQContext();
    $oSocket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'my pusher'); // use persistent_id
    if($oSocket instanceof \ZMQSocket) {

        $oSocket->connect("tcp://127.0.0.1:5555"); //
        $oSocket->send(json_encode($aUserData));
    }
}

public function logout() {
    //... here is the logout code, model call etc ....

    $aUserData = array();// user data comes from the SESSION with username, logintime, etc....

    $aUserData['topic'] = 'USER_LOGOUT'; // add the topic name

    $context = new \ZMQContext();
    $oSocket = $context->getSocket(\ZMQ::SOCKET_PUSH, 'my pusher'); // use persistent_id
    if($oSocket instanceof \ZMQSocket) {

        $oSocket->connect("tcp://127.0.0.1:5555"); //
        $oSocket->send(json_encode($aUserData));
    }
}

.

最後にビューファイルで、

<script>
var conn = new ab.Session('ws://yourdomain.dev:9000', // Add the correct domain and port here
    function() {
        conn.subscribe('USER_LOGIN', function(topic, data) {                
            console.log(topic);
            console.log(data);
        });

       conn.subscribe('USER_LOGOUT', function(topic, data) {                
            console.log(topic);
            console.log(data);
        });
    },
    function() {
        console.warn('WebSocket connection closed');
    },
    {'skipSubprotocolCheck': true}
);
</script>

.

: 基本的な考え方は、プッシャー クラスで単一のブロードキャスト関数を使用することでした。

于 2016-06-29T11:08:40.130 に答える
3

Websockets で PHPのベスト プラクティスを使用して 1 か月集中的に処理した後、クロスバー.io、PHP バックエンドの voryx/Thruway、フロントエンドの Autobahn|JS へのアプローチ変更しまし。これらのコンポーネントはすべてWAMP V2 Websocket 標準をサポートしており、私の要件を処理できます。

いくつかのリクエストがある場合は、上記のコンポーネントを使用して、上記の問題の解決策を投稿できます。

于 2015-04-02T17:20:12.897 に答える