【Java】UDP通信を利用したデータの送受信
本稿は、より速度が求められる環境において使われる、UDP通信をやっていきます。
UDP通信
UDP通信はコネクションを確立せずに通信します。
データを送信する側は目的のアドレスにデータを一方的に送りつけて終了するというシンプルな処理になります。
その分通信のオーバーヘッドがなくなり速度が速くなります。
ただし、データの整合性や、到達順序が保障されないなどといったデメリットもあります。
プログラムを組むうえでは、テストプログラムの段階ではUDPのほうが簡単かもしれませんが、本格的なアプリケーションで通信処理を実装する場合はUDPのほうが、考慮すべきことが多く難易度が高い気がします。
例えば、一度に送信できるパケットの量なども考慮しておかなければなりません。
DatagramSocketクラス
通信処理を行うクラスです。
データを送信する場合、何も指定せずインスタンス化、受信する場合はポート番号のみ指定します。
DatagramSocket sock = new DatagramSocket();//送信 DatagramSocket sock = new DatagramSocket(ポート番号);//受信
DatagramPacketクラス
データパケットをあらわすクラスです。
このクラスにバイト配列などを格納し、データを送信します。
受信時もこのクラスから取り出し処理を行います。
DatagramPacket packet = new DatagramPacket(バイト配列, データの大きさ,new InetSocketAddress(送信先ipやホストなど,送信先ポート番号));//送信 sock.send(packet);//パケットの送信
DatagramPacket packet = new DatagramPacket(バイト配列, データの大きさ);//受信 sock.receive(packet);//パケットの受信
データの送受信サンプル
UDPでのデータの送受信を行う、シンプルなサンプルを作ってみます。
クライアントが文字列を送信し、サーバが受信するだけです。
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; public class Client { public static void main(String[] args) throws IOException { String sendData = "UDPてすとですよ";//送信データ byte[] data = sendData.getBytes("UTF-8");//UTF-8バイト配列の作成 DatagramSocket sock = new DatagramSocket();//UDP送信用ソケットの構築 DatagramPacket packet = new DatagramPacket(data, data.length,new InetSocketAddress("localhost",10005));//指定アドレス、ポートへ送信するパケットを構築 sock.send(packet);//パケットの送信 System.out.println("UDP送信:"+sendData);//送信データにの表示 sock.close();//ソケットのクローズ } }
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.util.Arrays; public class Server { public static void main(String[] args) throws IOException { DatagramSocket sock = new DatagramSocket(10005);//10005ポートでUDP受信用ソケット構築 byte[] data = new byte[1024];//受信最大バッファ DatagramPacket packet = new DatagramPacket(data, data.length);//受信用パケットを構築 sock.receive(packet);//受信 System.out.println("UDP受信:"+new String(Arrays.copyOf(packet.getData(),packet.getLength()),"UTF-8"));//受信データの表示 sock.close();//ソケットのクローズ } }
UDP送信:UDPてすとですよ
UDP受信:UDPてすとですよ
DatagramChannelクラス
DatagramChannelを使用すると以前紹介したセレクタを利用してUDP通信することができます。
セレクタは下記の記事で紹介しました。
DatagramChannelもServerSocketChannelと同じくAbstractSelectableChannelを継承しているため、同じように使えます。
これを利用すると複数端末間の通信処理も簡単に実装できそうです。
バイト配列の取り扱いに便利なByteBufferを利用できるのも利点です。
DatagramChannelはopenメソッドでインスタンスを取得し、sendメソッドで送信処理を行います。
DatagramChannel channel = DatagramChannel.open(); channel.send(バイトバッファ, new InetSocketAddress(送信先ipやホスト, ポート番号));
DatagramChannel channel = DatagramChannel.open(); channel.bind(new InetSocketAddress(ポート番号)); channel.receive(バイトバッファ);//データの受信
DatagramChannelによる送受信サンプル
それではDatagramChannelを使った送受信のサンプルも作ってみましょう。
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.charset.StandardCharsets; public class Client { public static void main(String[] args) throws IOException { String sendData = "UDPチャネルのてすとですよ";//送信データ DatagramChannel channel = DatagramChannel.open();//DatagramChannelの作成 ByteBuffer bb = StandardCharsets.UTF_8.encode(sendData);//送信データをUTF8バイト配列に変換 channel.send(bb, new InetSocketAddress("localhost", 10003));//10003へ送信 System.out.println("UDPチャネル送信:"+sendData);//送信データの表示 channel.close();//チャネルクローズ } }
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.charset.StandardCharsets; public class Server { public static void main(String[] args) throws IOException { DatagramChannel channel = DatagramChannel.open();//データグラムチャネルの作成 channel.bind(new InetSocketAddress(10003));//受信ポートの指定(10003で受け付け) ByteBuffer bb = ByteBuffer.allocate(1024);//最大1024バイト受信バッファの作成 channel.receive(bb);//データの受信 bb.flip();//現在のデータを受信データとして確定させる System.out.println("UDPチャネル受信:"+StandardCharsets.UTF_8.decode(bb).toString());//UTF8でバイト配列からStringへ変換 channel.close();//チャネルのクローズ } }
UDPチャネル送信:UDPチャネルのてすとですよ
UDPチャネル受信:UDPチャネルのてすとですよ
これでUDP通信の基本処理もできると思います。
時間ができたら通信系のゲームも一本作りたいところですね。
ディスカッション
コメント一覧
まだ、コメントがありません