• ベストアンサー

TCP通信のプログラム(java)

javaを使ってTCP通信のプログラムを作りました。 そのプログラムは次のような動作をさせたいですが、途中までしか動作確認がとれません。 1. 送信側で指定したバイト数のデータを送信する。それにかかった時間を計測する。 2. 送信されたバイトデータを受信する。届いたバイト数の確認をするとともに、受信にかかった時間を計測する。 3. 受信側は1.で行った処理と同じようにして、届いたバイト数分のデータを返信する。 4. 3.で送信側に送信されたデータを受信して、受信時間を計測する。届いたバイト数を確認する。 2.までは、正常に動作します。正常な動作とは、 送信側は、指定した数のバイトデータを送信して、それにかかった時間を計る。 受信側は、送信されたデータを受信して、それにかかった時間を計り、届いたバイト数を確認する。ちなみにこの2つの時間はほぼ同じになります。 ここまではできています。 ですが、送信側が受信側で届いたバイト数分のデータを送信し、送信側でそのデータを受信してその時間を測るというコード(//*受信処理*//という行から下)を追加するとうまくいきません。 受信側では、//*受信処理*//という行から下を追加すると、うまくいきません。 送信と受信処理のコードを載せます。 送信側(送信バイト数は入力させます) Socket sock = new Socket(host, port); BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream()); BufferedInputStream in = new BufferedInputStream(sock.getInputStream()); //*送信処理*// // 送信データを送信する。 int count = 0; // write()の回数 System.out.println("<データ送信処理>"); start = System.nanoTime(); // 計測開始時間 for (int i = 0; i < Data; i++) {   try {     out.write(i);     out.flush();     count++;   } catch (IOException e) {     System.err.println((count + 1) + "つ目のバイト:書き込みエラー");   } } stop = System.nanoTime(); // 計測終了時間 System.out.println("送信完了"); System.out.println("送信されたバイト数:" + count); // 送信スループットを計算する。 // 結果を表示する。 //*受信処理*// // 変数を定義する。 long startNs = 0; // 受信前の時間のナノ秒を返す。 long stopNs = 0; byte[] buf = new byte[1000000]; int total = 0, part; // ストリームの終わりに達し,-1が返されるまで受信する。 System.out.println("<データ受信処理>"); startNs = System.nanoTime(); while ((part = in.read(buf, 0, buf.length)) != -1) {   total += part;   System.out.println(part); } stopNs = System.nanoTime(); System.out.println("受信完了"); System.out.println("受信されたバイト数:" + total); // 受信スループットを計算する。 // 結果を表示する。 // 出力ストリーム・ソケットをクローズする。 out.close(); sock.close(); 受信側のコードは補足欄に載せます。このコードだと、 送信側の計測結果は表示されますが、受信側で受信時間や受信速度などが表示されません。 送信側で通信を強制終了すると、その後に受信側は、結果を表示します。 データを片道ではなく往復させて、それらの処理時間を計測したいのです。うまくいかないのでアドバイスを頂きたいです。 このコードのおかしい部分が分かる方はアドバイスをお願いします。 コードが見にくくて意味がわからないかもしれませんが、そうならば、データを往復させてその時間を測るためのアドバイスをお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • junkUser
  • ベストアンサー率56% (218/384)
回答No.3

重箱の隅ですが >送信側と受信側の通信速度が一致したからです。 用語を間違って使っているだけだとは思いますが・・・ トランスポート層まで確立できているのですから、通信速度は必ず一致します。通信速度が一致しないと通信できないからです。 また、送信にかかる時間、受信にかかる時間は常に一致するとは限りません。 ネットワークドライバの仕様や、その他の影響が必ずあるからです。 送信時間、受信時間が一致することを確認したいのであれば、javaでは無理です。 むしろ、HUB経由のPC間をハードウェアレベルで nano sec オーダーの計測をしても誤差が出るはずです。その上、java の Socket 通信は TCP/IP を使用しているため 3way ハンドシェイクを隠蔽しています。 java の通信をより低レベルで確認するのでしたら、DatagramSocket を使ってはいかがでしょうか。 ついでに言っておくと nanoTime は Sparc マシン以外ではあまり正確な値は得られませんよ。 >毎回フラッシュするので当然だとは思いますが。 遅い原因がわかっていらっしゃるようですが、なんの目的で BufferedOutputStream をお使いで? データをすべて突っ込んでから最後に1回だけ flush するのが普通の使い方です。 毎回 flush するのでしたら、OutputStream に直接突っ込んだ方がコードは簡潔になりますよ。

debukawa
質問者

お礼

回答ありがとうございます。 いろいろ指摘していただいてありがとうございます。 たくさんのアドバイスをもとに試行錯誤した結果、 なんとかエラーを解決できました。 プログラミングに関しては初心者ですので、また質問させていただくと 思います。 その時はよろしくお願いします。

その他の回答 (2)

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.2

質問の内容と直接は関係ありませんが、送信側のプログラムが1バイト送信するごとにflush()を呼ぶ作りになっているのはなぜでしょう? そういう書き方をしたら通信速度にどのような影響が出るのかを見るための実験でしょうか。

debukawa
質問者

お礼

理由は、そうすることで送信側と受信側の通信速度が一致したからです。 同じデータに対する送信時間と受信時間を計測したので一致しないとおかしいと思いました。 一致はしましたが、すごく速度が遅くなりました。毎回フラッシュするので当然だとは思いますが。 1バイト送信するごとにflush()を呼ぶ作りにしないと、測定結果に誤差が出るためです。

  • junkUser
  • ベストアンサー率56% (218/384)
回答No.1

送信側の受信開始がわずかに速くて、受信開始の最初のループで-1になっているのではないでしょうか。 in.available() > 0 になってから受信開始すると良いと思います。 ただ、送信時間より受信時間のほうが短くなるかもしれません。

debukawa
質問者

お礼

回答ありがとうございます。 早速試してみます。

debukawa
質問者

補足

受信側のコードを載せます。 受信側では、//*送信処理*//という行から下を追加すると、うまくいきません。 ServerSocket server = new ServerSocket(servPort); Socket sock = server.accept(); BufferedInputStream in = new BufferedInputStream(sock.getInputStream()); BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream()); long startNs = 0; // 受信前の時間のナノ秒を返す。 long stopNs = 0; byte[] buf = new byte[1000000]; int total = 0, part; System.out.println("<データ受信処理>"); startNs = System.nanoTime(); while ((part = in.read(buf, 0, buf.length)) != -1) { total += part; } stopNs = System.nanoTime(); System.out.println("受信完了"); System.out.println("受信されたバイト数:" + total); // 受信スループットを計算して表示する。 //*送信処理*// int count = 0; // write()の回数 long start = 0; // 計測開始時間 long stop = 0; // 計測終了時間 System.out.println("<データ送信処理>"); start = System.nanoTime(); // 計測開始時間 for (int i = 0; i < 1000; i++) { try { out.write(i); out.flush(); count++; } catch (IOException e) { System.err.println((count + 1) + "つ目のバイト:書き込みエラー"); } } stop = System.nanoTime(); // 計測終了時間 System.out.println("送信完了"); System.out.println("送信されたバイト数:" + count); // 送信スループットを計算して結果を表示する。 in.close(); // 入力ストリームをクローズする。 sock.close(); // ソケットをクローズする。

関連するQ&A