web-dev-qa-db-ja.com

Ratchet WebSocketサーバーはクライアント自体にメッセージを送信できますか?

IPhoneアプリとサーバー間の永続的な接続にラチェット( http://socketo.me )を使用したい。そして、アプリとサーバーの間でデータを交換する必要があります。

この例から( http://socketo.me/docs/hello-world )私は関数onMessageを持っていることがわかりましたアプリがサーバーにマッサージを送信し、サーバーがアプリに応答を送信できるときに呼び出されます。

ただし、サーバーには、アプリからデータを取得せずにアプリにデータを送信する機能も必要です。たとえば、アプリとサーバー間の接続が確立されています。サーバーで何かが発生したため、アプリに新しいデータを送信する必要があります。どうすればそれを行うことができますか?それは可能ですか?

主な質問は、サーバーからアプリにデータを送信するにはどうすればよいですか?

助けてくれてありがとう。

18
lexa

それは確かに可能です。なんらかの方法でWebSocketサーバープロセスと通信する必要があります。これは、RPCまたはメッセージキューなど、何らかの形式のメッセージパッシングを使用して行うことができます。

ラチェット自体は、Reactイベントループに基づいています。これは、ラチェットとのあらゆる形式の通信をそのイベントループと統合する必要があることを意味します。 Reactホームページ すでに存在する統合のいくつかを見ることができます:

  • Predis/Async (メッセージパッシングにはredis pub/subを使用できます)
  • DNode-PHP (dnodeはTCPベースのRPCプロトコルです)
  • React/ZMQ (イベントループを ZeroMQ と統合します)
  • React/Stomp (STOMPプロトコルの実装、 RabbitMQ などのメッセージと通信できるようにします)
  • JCook21/ReactAMQP (React PHPのAMQPバインディング)

Ratchetのドキュメントには、 React/ZMQの使用方法に関するチュートリアル があり、どこからでもWebSocketサーバーにメッセージをプッシュできます。

13
igorw

ラチェットは [〜#〜] wamp [〜#〜] も実装します。これにはPubSubが含まれます。したがって、クライアントはいくつかのトピックをサブスクライブでき、他のクライアント(つまり、バックエンドインフラストラクチャで実行されている)にそれらのトピックを公開させることができます。つまり、AutobahnPythonベースのクライアントをRatchet経由でAutobahnAndroidベースのモバイルアプリまたはAutobahnJSベースのHTML5クライアントに公開することができます。

6
oberstet

私はまったく同じ質問をしました、そしてこれが私がしたことです。

hello worldチュートリアル に基づいて、SplObjectStorageを配列に置き換えました。私の変更を提示する前に、そのチュートリアルを実行して理解した場合、このソリューションに自分で到達するのを妨げた唯一のことは、おそらく SplObjectStorage が何であるかを知らないことであるとコメントしたいと思います。

class Chat implements MessageComponentInterface {
    protected $clients;

    public function __construct() {
        $this->clients = array();
    }

    public function onOpen(ConnectionInterface $conn) {
        // Store the new connection to send messages to later
        $this->clients[$conn->resourceId] = $conn;
        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        $numRecv = count($this->clients) - 1;
        echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
            , $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

        foreach ($this->clients as $key => $client) {
            if ($from !== $client) {
                // The sender is not the receiver, send to each client connected
                $client->send($msg);
            }
        }
        // Send a message to a known resourceId (in this example the sender)
        $client = $this->clients[$from->resourceId];
        $client->send("Message successfully sent to $numRecv users.");
    }

    public function onClose(ConnectionInterface $conn) {
        // The connection is closed, remove it, as we can no longer send it messages
        unset($this->clients[$conn->resourceId]);

        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "An error has occurred: {$e->getMessage()}\n";

        $conn->close();
    }
}

もちろん、それを本当に便利にするために、DB接続を追加し、それらのresourceIdを保存/取得することもできます。

0
Scott Yang