Ratchetを使ったチャットシステムでのsubscribe登録機能について
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 3,412
環境
php5.6
ratchet:v0.3.6
PHP版のRatchetを用いて、チャットシステムの勉強をしています。
下記のチュートリアルの内容を組み合わせて、チャットする各ユーザーを
RoomIDのようなものでチャット部屋を分けて、その中でのみメッセージを
配信できるようにしたいと考えています。
(zeroMQを利用してtopicにRoomIDを割り当てるという方法を試しています。)
http://socketo.me/docs/hello-world
http://socketo.me/docs/push
そこでchat-serverは下記の通りのコードにしています。
chat-server.php
<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;
require dirname(__DIR__) . '/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();
chat.php
<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\ComponentInterface;
class Chat implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients->attach($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 $client) {
if ($from !== $client) {
// The sender is not the receiver, send to each client connected
$client->send($msg);
}
}
}
//ここはチュートリアルから追加しています。
public function onSubscribe(ConnectionInterface $conn, $topic) {
if (!array_key_exists($topic->getId(), $this->subscribedTopics))
{
$this->subscribedTopics[$topic->getId()] = $topic;
}
}
//ここはチュートリアルから追加しています。
public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) {
$json = json_decode($event);
$topic->broadcast(Security::htmlentities($json->input));
}
public function onClose(ConnectionInterface $conn) {
// The connection is closed, remove it, as we can no longer send it messages
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
}
クライアントはまず、webのページに入った直後にchat-serverに接続してtopicにRoomIDを割り当てたいと考えています。
chat.html
<script src="http://autobahn.s3.amazonaws.com/js/autobahn.min.js"></script>
<script>
var conn = new ab.Session('ws://localhost:8080',
function() {
conn.subscribe('RoomID', function(topic, data) {
// This is where you would add the new article to the DOM (beyond the scope of this tutorial)
console.log('New article published to category "' + topic + '" : ' + data.title);
});
},
function() {
console.warn('WebSocket connection closed');
},
{'skipSubprotocolCheck': true}
);
</script>
しかし、下記のようなエラーがクライアント側で生じて、一旦接続しますが、すぐに切られてしまいます。
WebSocket connection to 'ws://localhost:8080/' failed: Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received
autobahn.min.js:62
対処方法がわからず、アドバイス頂きたくよろしくお願いします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
お使いのPHPライブラリ(Ratchet)とJSライブラリ(AutobahnJS)の扱っているプロトコル(WAMP)のバージョンが違うためにハンドシェイクに失敗してるようにみえます。
RatchetがWAMP v1に、AutobahnJSがWAMP v2に準拠している。
Ratchetの公式ページにはWAMPのバージョンが記載されてませんでしたが(ちらっと覗いただけなのでどこかに書いてあるかも)、
以下のIssueでRatchetの作者(っぽい人)がロードマップからWAMPv2のサポートを取り下げたと言ってますので、おそらくRatchetはWAMPv1準拠だと思われます。
Support WAMPv2 · Issue #168 · ratchetphp/Ratchet
https://github.com/ratchetphp/Ratchet/issues/168#issuecomment-55339203
I've decided to remove WAMPv2 support from the roadmap, at least for the time being.
対して、AutobahnJSは公式ページにWAMPv2に準拠してると記載ありました。
Autobahn|JS — AutobahnJS 0.9.4 documentation
http://autobahn.ws/js/
Features
supports WAMP v2, works with any WAMP server
ですので、RatchetとAutobahnJSのプロトコルverを合わせられれば解決できそうですが(AutobahnJSの古いバージョンを探すとか?)、
特にPHPに拘る理由がなく、チャットの仕組みを勉強されたいとのことでしたら、
まずはNodeJSなどで試されるのが手軽で良いかもしれません。
「NodeJS チャット」で検索すると沢山ヒットします。
根本的な解決ではなくてすみません。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.13%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/03/20 21:23
2017/03/20 21:33
2017/03/20 21:50 編集
では、Ratchetに代わるPHPライブラリを探してみるのも手ですね。
上記GitHub IssueでRatchetの作者(っぽい人)が言及してるPHPライブラリがこちらなのですが、
Autobahnとも相性良さそうなこと書いてますので、選択肢の一つとして提案しておきますね。
voryx/Thruway: PHP Client and Router Library for Autobahn and WAMP (Web Application Messaging Protocol) for Real-Time Application Messaging
https://github.com/voryx/Thruway
2017/03/20 22:15
minimized and gzipped版は「Uncaught ReferenceError: ab is not defined」というエラーがでて
クライアント側のchat.html のvar conn = new ab.Session('ws://localhost:8080',というところで止まってしまうようです。only minimized版とDevelopment版は当初のエラーが出てしまいました。
2017/03/21 21:29