この質問をする前に、私はSOに関する厳しい質問を読んで最善を尽くしました(タグ付きのラチェットと同様の問題に対処しましたが、役に立ちませんでした。注目されなかった質問もしたので、別の質問を書くために削除しました(うまくいけばより明確に)。
私の最終的な目標は、ラチェットを使用して1対1のプライベートチャットアプリケーションを構築することです。特定のユーザーにメッセージを送信できないことを除いて、すべてが正常に機能しています。
ログインしたすべてのユーザーは、Webサイトの保護された領域にアクセスしながら、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がどれであるかを知ることができます。しかし、彼はどのようにしてそのユーザーの接続がどれであるかを知るのでしょうか?つまり、ユーザーIDでインデックス付けされた配列にWebSocket接続を格納する必要があります。
<?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;
}
}
そして、WebSocketサーバー:
<?php
require dirname(__DIR__) . '/vendor/autoload.php';
use RealTime\Pusher;
$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');
$pull->on('message', array($pusher, 'onMessageEntry'));
$webSock = new React\Socket\Server($loop);
$webSock->listen(8080, '0.0.0.0');
$webServer = new Ratchet\Server\IoServer(
new Ratchet\Http\HttpServer(
new Ratchet\WebSocket\WsServer(
new Ratchet\Wamp\WampServer(
$pusher
)
)
),
$webSock
);
$loop->run();
?>
質問:
user_id
接続を開いているときにクライアント側からログインを送信する方法。クライアントの配列に($client[user_id]=$conn
ではなく$client[recourceId]=$conn
)インデックスを付けることができるように、WebSocketサーバーに値を設定する必要があります。javascript関数を試しましたsend
が、送信されたデータをどこで受信するかわかりません(onMessage
何も印刷していません)。
onMessage
メソッドがMessageComponentInterface
実装されていても実行されないのはなぜですか(onMessageEntry
メソッド+$pull->on('message', array($pusher, 'onMessageEntry'));
コード行があるためですか?
ありがとうございました。
これは私が見つけたものであり、このソリューションを強化するための提案は大歓迎です。
ラチェットSessionProviderを使用できます。これには、示されているようにSymfonyカスタムセッションハンドラーの1つを使用する必要があります。私は次のコードでを使用します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();
?>
次に、私のスタブクラスは次のようになります。
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']);
}
ただし、以前は、Webサーバー(最初のページを返すコントローラー内)のセッションにユーザーIDを追加しました。
$user = $this->getUser();
$request->getSession()->set('current_user_id', $user->getId());
PS:
PdoSessionHandlerへの移行は、これを実装することで実行できます(Symfony)。
私はまだ2に答えることができませんが、置くことができるすべてのロジックは、一時的にニーズを満たすonMessage
ように移動されましonMessageEntry
た。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加