2011年6月10日金曜日

UDPホールパンチング、その1

P2Pを行おうとすると、ポートの解放等手間がかかります。
だいたいはルーターの設定をいじってやれば済むのですが、やはり素人ではなかなか手がだせません。
設定用のHtmlをプログラムからリクエストとばしてやって、特定の機器では自動的にポート解放をするということもやろうと思えばできますが、さすがに勝手にプログラムがポートをあけるなんて恐ろしい話です。(Basic認証くらいなら、ダイアログを開いて入力してもらって・・・みたいな感じですかね。)

というわけでFlashのP2P実装RtmfpでもつかっているUDPホールパンチングという技術をちょっと触ってみました。
今回はその初回です。
やることは結構単純で以下の手順です。
まず適当なPCでサーバーにUDPによる接続を実行する。するとそのPCが接続につかったIPアドレスとポートがわかる。
別のPCが先のIPアドレスとポート宛にメッセージをおくると、メッセージがとどく。
この手順で互いにIPアドレスとポートを交換しあうとP2Pで通信ができるというもの。
まぁ、かなり乱暴な説明です。

ともあれJavaでちょこっと作ってみました。
https://github.com/taktod/udptest
コメントもかかずにパパッとつくっただけなので、わかりにくいと思いますが、次の動作をします。
実行可能jarファイルをserver.jarとclient.jarつくって
1:サーバーを立ち上げる。
2:クライアントを実行するとサーバーに接続し、testという文字列を送信する。(ダミーデータ)
3:サーバーはtestを受け取るとそこから接続してきたユーザーのIPアドレスと利用中のポートを取得してMapにいれて保持しておく。
4:サーバーから接続中のクライアントには、新しいクライアントの情報を送る。
5:サーバーから新しいクライアントには、接続中のクライアントの情報を送る。
6:クライアント情報を受け取ったクライアントはinitという文字列を情報の宛先に送信する。(ダミー)
6の時点で全クライアントが互いにinitという文字列データ送信を相互におこなったことになる。
7:標準入力のデータを受け取ったクライアントは他のクライアントにそのデータを送る。(P2Pの動作実行)

という次第です。
注意点は、しばらく放置するとタイムアウトになるのか接続できなくなるみたいです。
この部分は、サーバーやクライアント同士で適当にPingのやりとりをするように実装すればOKかと思います。

Javaでかけちゃうのが面白い。
中央サーバーをGAEにでもおいておき、P2PのクライアントはJavaAppletにとかできたら、かなりおもしろいことできるんじゃない?

1 件のコメント: