外部からAndroidエミュレータへTCPまたはUDPで通信する方法

備忘録エントリ。
Androidエミュレータは内部的に仮想ルータが動作することにより、ホストマシン(エミュレータが動作しているマシン)のネットワークとは別に、10.0.2.0/24のネットワークで動作している。このため、外部からエミュレータへの通信をするにはちょっとした準備が必要になる。

方法は、http://developer.android.com/intl/ja/guide/developing/devices/emulator.html#redirections(日本語訳はSign in - Google Accounts)に記載されているが、要はホストマシンのポートで受けた通信をエミュレータのポートへ転送させるようにすることで対応する。
手順は以下の通り。

1.エミュレータを起動
2.telnetlocalhostエミュレータコンソールポート(1つ目のエミュレータなら5554)へ接続
3.エミュレータコンソールで以下のコマンドを実行

redir add tcpまたはudp:ホストマシンのポート番号:エミュレータのポート番号

例.ホストマシンのTCP/5000への通信をエミュレータTCP/6000へ転送する場合

redir add tcp:5000:6000

確認

redir list
tcp:5000 => 6000と出力される。

設定すると、ホストマシン上で0.0.0.0に対して、ホストマシンのポート番号に指定したポート(上記例では5000)が開き、待ち受け状態になるので、通信したいマシンからホストマシンのそのポートへ通信してやればエミュレータの指定ポートへ転送される。
なお、転送をやめる場合は以下のようにする。

redir del tcp:5000

4.実際に通信して確認してみる
なぜか、http://developer.android.com/intl/ja/guide/developing/devices/emulator.htmlにも載ってないのだが、
エミュレータコンソールで、パケットキャプチャが可能なのでそれで確認してみる。
キャプチャの開始は以下のコマンド。

network capture start ホストマシンのキャプチャファイル出力先フルパス

例.ホストマシンの/tmp/hoge.cap(WindowsならC:\tmp\hoge.cap)へ出力する場合

network capture start /tmp/hoge.cap

で、telnetなりnetcatなりでホストマシン向けに通信する。

nc ホストマシンのIPアドレス 5000

キャプチャの停止は以下のようにする。

network capture stop

あとは、出力されたファイルをWiresharktcpdumpで見てみると、10.0.2.2(ホストのループバックアドレスエイリアス) -> 10.0.2.15(エミュレータIPアドレス)へ通信が行われているのが確認できる。

なお、ポート転送の設定はエミュレータコンソールだけでなく、adbコマンドでも可能。

adb forward tcp:ホストマシンのポート番号 tcp:エミュレータのポート番号

この場合、エミュレータだけでなく実機でも設定可能。