UDP Javaプログラミング Java補足

User Datagram Protocol
1つのUDPパケットで運ぶことのできるデータは、下位層のIPパケット長の制約を受けます。 
まず標準のIPパケットでは、 1回の送信で、最大では65515bytes(65535bytesから、IPヘッダの最低サイズ20bytesを引いた値)の データを送信できます。(IPヘッダ・オプションが付くと、さらに小さくなる)。
よって、その中のデータに入っているUDPパケットが65515bytesとなる訳ですが、 UDPヘッダーのサイズが8bytes固定長で、これで減算した65507bytesがUDPの最大データ長になります。
なお、チェックサムの計算ではUDPヘッダー(8bytes)+擬似ヘッダー(12bytes) なので、計65527 bytesです。
UDP ではサムチェックよりパケットに破損がないか調べられます。
しかし、それでエラーを検出しても、単にそのパケットを破棄するだけです。
またパケットの順序が違ってもそれを並べ替えることもしません。
パケットを紛失してもそれを知るすべもありません。
ですがUDP で受け取ったデータは、とりあえず破損していないものとなります。

UDPSndTest.javaで、UDPRecTestのプログラムを呼び出すことで、一つのプログラムにまとめたプログラムにする検討をしてみよう。
例えば、 UDPSndTest.java の出力の繰り返しの直前で、 UDPRecTest.main(null);
UDPRecTestのmainを実行させてみよう。
(UDPSndTest.java の中に、UDPRecTest.javaのソースをコピーする必要は ありません。UDPRecTestのクラスができているのですから・・)
この場合は、送信文字列の入力ができないでしょう。なぜならrecSocket.receiveの受信命令がブロック(待ち)状態になっているからです。

つまり、一つにまとめるには、送信と受信を別のスレッドで動作させる必要があります。 その場合の実現方法は、いくつかありますが、その一つの例でUDPSndTest.javaを 紹介します。

import java.io.*;//BufferedReadered用
import java.net.*;//DatagramSocket、InetAddress用
public class UDPSndTest {
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.print("送信先IPアドレス>");
		InetAddress inet = InetAddress.getByName(  br.readLine()  );
		int portNumber = 59152;//ポート番号
		DatagramSocket sendSocket = new DatagramSocket();//UDP送信用ソケット

		Thread thread = new Thread() {
			public void run(){
				try{
					UDPRecTest.main(null);
				}
				catch(Exception e){
					e.printStackTrace();
				}
			}
		};
		thread.start();

		for(;;){
			System.out.print("送信文字列>");
			String msg = br.readLine();//送信メッセージキー入力
			if(msg.equals("")) {
				sendSocket.send(new DatagramPacket(new byte[0], 0, inet, portNumber));//送信
				break;
			}

			msg = "ここはsから始まる学籍番号に変更" + msg;
			byte[] buf = msg.getBytes("MS932");//バイト列に変換
			DatagramPacket packet;
			packet = new DatagramPacket(buf, buf.length, inet, portNumber);
			//IPアドレス、ポート番号も指定
			sendSocket.send(packet);//送信
			System.out.println(sendSocket.getLocalPort() + "のポートを使って送信します。");
		}
		sendSocket.close();//ソケットを閉じる
	}
}