初学者です。不十分な知識で僭越ながら質問させてください。よろしくお願いします。
実現したいこと
Javaのソケット通信において, 勉強と動作確認のため, Nagleアルゴリズムによる遅延をわざと発生させたいです.
現在は1sごとに4byteクライアント側から送信しており, クライアント側送信時刻とサーバ側送信時刻をコンソールで見ています.
小さいデータを送信するとNagleバッファに入り, 送信時刻と受信時刻に200ms程の差異が現れると思うのですが, 現在ほぼ時間の差異はありません.
Nagleアルゴリズムによる遅延はどうすれば発生するのでしょうか? ご教授お願い致します.
該当のソースコード
参照元コード https://oshiete.goo.ne.jp/qa/7317690.html
サーバ側
java
1public class Server { 2 public static ServerSocket ss = null; 3 public static Socket soc = null; 4 private static InputStream is = null; 5 private static OutputStream os = null; 6 7 public static void main(String[] args) { 8 9 try { 10 // サーバソケット生成 11 ss = new ServerSocket(5000); 12 soc = ss.accept(); 13 is = soc.getInputStream(); 14 Thread rcvTh = new ServerRcvThread(is); 15 rcvTh.start(); 16 // 10秒スリープ 17 try { 18 Thread.sleep(10000); 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 // スレッド停止 23 rcvTh.stop(); 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } finally { 27 try { 28 is.close(); 29 soc.close(); 30 ss.close(); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 } 35 } 36} 37class ServerRcvThread extends Thread { 38 private static InputStream ins = null; 39 40 ServerRcvThread(InputStream is) { 41 this.ins = is; 42 } 43 44 public void run() { 45 DateFormat format = new SimpleDateFormat("yyyy MM dd hh:mm:ss.SSS"); 46 byte rcvData[] = new byte[16]; 47 int size = 0; 48 try { 49 while (true) { 50 // データ読込み 51 size = ins.read(rcvData); 52 System.out.println("size:" + size + "byte" + " 受信時刻 = " + format.format(new Date())); 53 } 54 } catch (IOException e) { 55 e.printStackTrace(); 56 } 57 } 58}
クライアント側
java
1public class Client { 2 private static Socket soc = null; 3 private static OutputStream os = null; 4 private static InputStream is = null; 5 6 public static void main(String[] args) { 7 try { 8 // ソケット生成 9 soc = new Socket("127.0.0.1", 5000); 10 soc.setTcpNoDelay(false); //明示的にNagleアルゴリズムオン 11 os = soc.getOutputStream(); 12 Thread sndTh = new ClientSndThread(os); 13 sndTh.start(); 14 // 10秒スリープ 15 try { 16 Thread.sleep(10000); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 } 20 // スレッド停止 21 sndTh.stop(); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 } finally { 25 try { 26 is.close(); 27 os.close(); 28 soc.close(); 29 } catch (IOException e) { 30 e.printStackTrace(); 31 } 32 } 33 34 } 35} 36 37class ClientSndThread extends Thread { 38 private static OutputStream ous = null; 39 40 ClientSndThread(OutputStream os) { 41 this.ous = os; 42 } 43 44 public void run() { 45 DateFormat format = new SimpleDateFormat("yyyy MM dd hh:mm:ss.SSS"); 46 byte sndData[] = new byte[4]; 47 sndData[0] = 0x04; 48 sndData[1] = 0x03; 49 sndData[2] = 0x02; 50 sndData[3] = 0x01; 51 try { 52 while (true) { 53 // データ書込み 54 ous.write(sndData); 55 ous.flush(); 56 System.out.println("データ送信" + " 送信時刻 = " + format.format(new Date())); 57 // 1秒スリープ 58 try { 59 Thread.sleep(1000); 60 } catch (Exception e) { 61 e.printStackTrace(); 62 } 63 } 64 } catch (IOException e) { 65 e.printStackTrace(); 66 } 67 } 68} 69
コード改修(11.22)
サーバ側
java
1import java.io.IOException; 2import java.io.InputStream; 3import java.io.OutputStream; 4import java.net.ServerSocket; 5import java.net.Socket; 6import java.text.DateFormat; 7import java.text.SimpleDateFormat; 8import java.util.Date; 9 10public class Server 11{ 12 public static ServerSocket ss = null; 13 14 public static Socket soc = null; 15 16 private static InputStream is = null; 17 18 private static OutputStream os = null; 19 20 public static void main(String[] args) 21 { 22 23 try 24 { 25 // サーバソケット生成 26 ss = new ServerSocket(5000); 27 soc = ss.accept(); 28 soc.setTcpNoDelay(true); 29 is = soc.getInputStream(); 30 os = soc.getOutputStream(); 31 32 DateFormat format = new SimpleDateFormat("yyyy MM dd hh:mm:ss.SSS"); 33 byte sndData[] = new byte[4]; 34 sndData[0] = 0x01; 35 sndData[1] = 0x02; 36 sndData[2] = 0x03; 37 sndData[3] = 0x04; 38 39 while (true) 40 { 41 byte rcvData[] = new byte[16]; 42 int size = 0; 43 // データ読込み (受信するまで待つ) 44 for (int tmp = 0; tmp <= 1; tmp++) 45 { 46 size = is.read(rcvData); 47 System.out.println("データ受信。サイズ : " + size + "byte. 送信時刻 = " + format.format(new Date())); 48 if (size == 8) 49 { 50 break; 51 } 52 } 53 // clientからの送信が200ms遅延してる. ACK遅延により返答も200ms遅延 54 // 上記要因を踏まえて3回目以降のトリガー 55 os.write(sndData); 56 os.flush(); 57 System.out.println("データ送信" + " 送信時刻 = " + format.format(new Date())); 58 } 59 } 60 catch (IOException e) 61 { 62 e.printStackTrace(); 63 } 64 finally 65 { 66 try 67 { 68 is.close(); 69 os.close(); 70 soc.close(); 71 ss.close(); 72 } 73 catch (IOException e) 74 { 75 e.printStackTrace(); 76 } 77 } 78 } 79}
クライアント側
java
1import java.io.IOException; 2import java.io.InputStream; 3import java.io.OutputStream; 4import java.net.Socket; 5import java.net.UnknownHostException; 6import java.text.DateFormat; 7import java.text.SimpleDateFormat; 8import java.util.Date; 9 10public class Client1 { 11 12 public static void main(String[] args) { 13 14 Thread client = new ClientThread(); 15 client.start(); 16 try { 17 //Thread.sleep(1000); 18 client.join(); 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 } 23} 24 25class ClientThread extends Thread{ 26 private static Socket soc = null; 27 private static OutputStream os = null; 28 private static InputStream is = null; 29 30 public void run() { 31 try { 32 // ソケット生成 33 soc = new Socket("172.23.56.83", 5000); 34 soc.setTcpNoDelay(false); 35 is = soc.getInputStream(); 36 os = soc.getOutputStream(); 37 38 DateFormat format = new SimpleDateFormat("yyyy MM dd hh:mm:ss.SSS"); 39 byte sndData[] = new byte[4]; 40 sndData[0] = 0x04; 41 sndData[1] = 0x03; 42 sndData[2] = 0x02; 43 sndData[3] = 0x01; 44 45 for (int cnt = 0; cnt <10; cnt++) { 46 // 1回目送信(即送信される) 47 os.write(sndData); 48 os.flush(); 49 System.out.println("データ送信" + " 送信時刻 = " + format.format(new Date())); 50 // 0.01秒スリープ 51 try { 52 Thread.sleep(10); 53 } catch (Exception e) { 54 e.printStackTrace(); 55 } 56 // 2回目送信(1回目のACKが遅延ACKにより200ms遅延) 57 // 加えてNagleにより送信も200ms遅延 58 os.write(sndData); 59 os.flush(); 60 System.out.println("データ送信" + " 送信時刻 = " + format.format(new Date())); 61 62 byte rcvData[] = new byte[16]; 63 int size = 0; 64 // データ読込み 65 size = is.read(rcvData); 66 System.out.println("データ受信。サイズ : " + size + "byte. 送信時刻 = " + format.format(new Date())); 67 } 68 } catch (UnknownHostException e1) { 69 e1.printStackTrace(); 70 } catch (IOException e1) { 71 e1.printStackTrace(); 72 } finally { 73 try { 74 is.close(); 75 os.close(); 76 soc.close(); 77 } catch (IOException e) { 78 e.printStackTrace(); 79 } 80 } 81 } 82}
結果
log
1Nagleオンの場合 2データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:05:20.537 3データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:05:20.584 4データ送信 送信時刻 = 2019 11 22 01:05:20.584 5データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:05:20.584 6データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:05:20.631 7データ送信 送信時刻 = 2019 11 22 01:05:20.631 8データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:05:20.631 9データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:05:20.678 10データ送信 送信時刻 = 2019 11 22 01:05:20.678 11データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:05:20.678 12データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:05:20.724 13...
log
1Nagleオフの場合 2データ受信。サイズ : 8byte. 送信時刻 = 2019 11 22 01:22:21.897 3データ送信 送信時刻 = 2019 11 22 01:22:21.897 4データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:22:21.900 5データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:22:21.901 6データ送信 送信時刻 = 2019 11 22 01:22:21.901 7データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:22:21.901 8データ受信。サイズ : 4byte. 送信時刻 = 2019 11 22 01:22:21.917 9データ送信 送信時刻 = 2019 11 22 01:22:21.917 10...
環境
OS : win10
JDK : 1.8
IDE : eclipse
サーバとクラインアントは同一ホストで行なってました。
回答1件
あなたの回答
tips
プレビュー