2013年3月27日

PeerJS を試してみる

Chrome の stable が 26 になったことだし PeerJS を試す頃合いかなと思ってやってみた。
このページのデモは PC の Chrome で試して下さい。

PeerJS とは

WebRTC というブラウザ同士がサーバなしで通信しあって(要するにP2P)ビデオチャットなどができる仕組みの一部として自由なデータの送受信もできる機能があって、そこの部分を簡潔にラッピングしてくれるライブラリ。だと思う。あまり詳しくない。詳しくないからやってみようとしてる。
通信は UDP を使うことになるのでルータの内側からだったりするとちょっとハードル高そう。その辺で起こる問題をある程度上手く解決してくれる STUN サーバというのもあるらしい。まあなんか上手くやってくれるんだろう。知らなくても使える状態になってるに違いない。きっとそうだ。

まずサーバ側を準備してみる

PeerJS 側でサーバを用意してくれているみたいなので、ここでアカウント作成すれば簡単に使えるようになるようだ。まずはこれを使ってみよう。

名前、メールアドレス、パスワードを送るとメールが届き、新しい API キーを作成できる画面にくる。「Create new API key」ボタンを押すと最大同時接続数を入力する画面が出てくるけど、取りあえず初期設定のまま進むと API キーが発行された。

この API キーを使ってみよう。

ページ側を準備してみる

まずは PeerJS のトップページの頭にあるデモをそのまま作ってみる。
これを見る限り、someid というユーザーと anotherid というユーザーが決め打ちの状態で、anotherid から someid に対してデータを送信する、というデモっぽい。
demo1.html を開いて、Developer Tools のコンソールを開いておいて、その状態で demo2.html を開くと、demo1.html 側のコンソールに「hi!」というメッセージが出てくる。
(でない場合はなんかネットワーク周りの設定がおかしいような気がする)

このタイミングで、Windows ファイアウォールから報告がきた。突然 UDP 通信始めたから怒られたんだろう。ブロックを解除するを選んでおいた。

XP ですかwwwwwwwwwww


この状態で更にもうひとつ demo1.html を開くと、「Failed to load resource: the server responded with a status of 401 (Unauthorized)」というメッセージがいくつか出た。someid というユーザーは既に存在しているから開始に失敗したんだろうと思う。
もしあなたが demo1.html を踏んだ時点でエラーが色々出ているなら同じ原因だと思う(ブラウザが違うとか、PeerJS の仕様が変わった、とかでないなら……)ので、自分で API キーを取るなりサーバを準備するなりして試すといいと思います。

ページ側の改良を試みる

取りあえず2つユーザー ID が決め打ちになっていると色々都合が悪いのでここを直したい。
あと、demo2.html の方ではメッセージの受信をしていないので、ここで受信するようにすれば双方向通信が出来るようになるはずなのでそうしたい。

面倒なので、ひとまず prompt で入力させたりする方向で妥協した。
基本的な流れは同じだけど、ユーザー ID 入力機能が付いたのでページが統合された。

まずアクセスするとユーザー ID を聞かれるので、適当に入力する。
別タブで更にもうひとつ開いて、今度はさっきとは別のユーザー ID を適当に入力する。
この時点で2つの接続はまだお互いを知らない状態。To でもう一方のユーザー ID を入力して、メッセージを送るとページの一番下に追記される。
conn.on('open') のタイミングで相手を見つけ出すために若干時間掛かるのと、データ送信の度に相手を探し直してるのは処理としては微妙なのかも知れないけど取りあえずはそうした。

そろそろドキュメントを見ようかな

何も見ずにやってたけど、ドキュメントもあるので少し見てみた。
Peer を new する時の id は省略することができて、省略された場合サーバ側で自動生成されるらしい。そして自動生成されたものは作成された open イベントの引数として渡されてくるようだ。
peer インスタンスの id プロパティでも参照できるみたいだけど、サーバ側で生成されるまでは取得できないからイベント側で取得すればいい、ってことね。なら prompt は廃止しよう。

あと、日本語を書いて送信するとちょっと挙動がおかしい。
これは多分 peer.connect(id, [options]) の serialization を適切に設定すれば回避できそう。
binary と binary-utf8 というのがあるし。binary-utf8 ってよく意味がわからないけど、分かれてるってことは多分負荷の問題とかだろう。

peer.connect(id, [options]) の戻り値は peerjs.DataConnection で、connection.close() / connection.send(data) がメソッドとして存在していて、イベントは open / close / data / error が存在するみたいだから、conn を接続管理させることもできそうではある。
でも conn の close イベントが存在するってことは存在確認自体も PeerJS 側で面倒見てそう(UDP なんだから普通はちゃんと取れないはず)だし、自作しないほうがいいのかも。

PeerJS のソースを見てみたら、peer.connect(id, [options]) を呼んだ時既存の接続があるならそれを返す仕組みがあるみたいだから、こっちではそこは面倒を見る必要はないっぽい。
ユーザー ID は自動生成されるようになったので入力する必要がなくなって、日本語の送受信もできるようになった。
ユーザー ID がランダム生成になったので、少なくとも知っている人の ID を適当に入力して通信を始めるような使い方はできなくなった。あとランダムだとどれが誰かわかりにくいので、取りあえず名前入力欄を作って、送信元ユーザ ID は title 属性に入れるようにした。

雰囲気は大体わかってきたが

で、何作ろうかな。
結局のところこのままでは一人で始めた時にどこに誰に連絡が取れるのかわからない状態だし、ユーザー一覧返せる仕組みがないとコミュニケーション無しでいきなり使い始められるサービスというのは厳しそうだな。
Clip to Evernote