プロジェクト

全般

プロフィール

Javaプログラミング UDP通信

はじめに

インターネットプロトコルのUDP(User Datagram Protocol)を使ってプログラム間の通信を行うプログラミングをJavaで行います。
UDPはコネクションレスで輻輳や再送といった制御がなく、複数のデータグラムの順序は保証がないプロトコルです。
同一データグラムが複数送られることもあり得ます。
UDPのデータグラムサイズは、IPv4では65507バイトまで、IPルーティング上で一つのデータグラムがIPフラグメント(複数に分割)されることはありますが、受信側のUDP/IPスタックでフラグメントからデータグラムを再構成するのでアプリケーション上では1つのデータグラムは1回で読み出されます。

JavaのUDP通信ライブラリ

Javaは標準でUDP/IP通信を行うためのクラスライブラリとして、次の2種類が提供されています。

  • java.netパッケージで提供されるDatagramSocketおよびDatagramPacket
  • java.nio.channelsパッケージで提供されるDatagramChannel

java.netパッケージは初期のJavaから提供されているAPIで、ブロッキングI/O、データの入出力は byte配列で行います。
java.nio.channelパッケージは Java SE 1.4以降で提供されているAPIで、ブロッキングI/OのほかノンブロッキングI/O、データの入出力は java.nio.ByteBufferで行います。

java.nio.channels.DatagramChannel

生成

次のstaticメソッドを呼びます。
static DatagramChannel open() throws IOException

チャネルは使用終了後に必ずcloseする必要があります。

connectするかどうか

DatagramChannelは、任意の宛先を指定して送信する方法の他、ソケットにconnectして特定の宛先と送受信する方法があります。このconnectはTCP通信とは違い擬似的なものでローカル操作のみとなり、ブロッキングされません。

connect時の送受信メソッド

readメソッドとwriteメソッドを使います。引数にはByteBufferおよびByteBuffer[]を指定、戻り値は読み書きしたバイト数が得られます。connectしたソケットの宛先とのみUDP送受信を行います。

非connect時の送受信メソッド

sendメソッドとreceiveメソッドを使います。sendメソッドは引数にByteBufferおよびSocketAddressを指定し、戻り値は送信したバイト数が得られます。sendメソッドを呼ぶたびに引数SocketAddressで指定する宛先にUDP送信をします。receiveメソッドはbindしたポートでUDP受信を行い、戻り値は送信元のSocketAddressが得られます。

int send(ByteBuffer b, SocketAddress a) throws IOException
SocketAddress receive(ByteBuffer b) throws IOException

アドレスへのbind

UDPで受信を待ち受けるときは、ポート番号を指定してbindをします。マルチホーム(複数NIC)では、どのIPアドレス(NIC)で待ち受けるか、あるいは全てのIPアドレスで待ち受けるかを指定します。

タイムアウト(ブロックモード)

ブロックモードでは、receiveメソッドやreadメソッドは実際にデータを受信するまでメソッドが復帰しません。データがこなければずっと待ち続けています。
DatagramChannelは、InterruptibleChannelインタフェースを実装しているので、非同期にクローズすること、またはブロックしているメソッドを実行しているスレッドへの割込みをすることができます。

一定時間データが受信しなかったらメソッドを復帰したい場合は、次の方法があります。

  1. DatagramChannelをクローズ
  2. DatagramChannelのブロックするメソッドを呼び出したスレッドにinterrupt

1. のクローズは、タイムアウトで中断すると次に通信するときはopenから始めなくてはなりません。そこで、2.のメソッドを実行するスレッドに割り込み(interrupt)することでタイムアウトを実現します。

  • 注)DatagramChannelではソケットオプション SO_TIMEOUT はサポートされていません

プログラミング例

UDP受信

参考文献

  • Pit,Esmond. 2005. Fundamental Networking in Java . London:Springer. (ピット,エズモンド. 岩谷 宏(訳)(2007). Javaネットワークプログラミングの真髄 . ソフトバンククリエイティブ)