質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

24976閲覧

【Java】Socket.close()などで発生するIOExceptionの発生条件

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2014/11/15 11:26

Java8でソケット通信プログラムを作成しています。
サーバープログラムのコードについての質問となります。

lang

1package server1; 2 3import java.io.IOException; 4import java.net.ServerSocket; 5import java.net.Socket; 6import java.util.logging.Level; 7import java.util.logging.Logger; 8 9public class Server1 { 10 public static void main(String[] args) { 11 ServerSocket srvSocket; 12 Socket socket; 13 try { 14 srvSocket = new ServerSocket(30000); 15 socket = srvSocket.accept(); 16 17 // ... 18 19 socket.close(); 20 } catch (IOException ex) { 21 Logger.getLogger(Server1.class.getName()).log(Level.SEVERE, null, ex); 22 } 23 } 24} 25

このサーバープログラムでは、srvSocket = new ServerSocket(30000);, socket = srvSocket.accept();, socket.close();の全てでIOException例外が発生します。

Java 8 APIドキュメントでこれらの例外の説明は順に以下の通りに書かれていました。

  • ソケットを開いているときに入出力エラーが発生した場合
  • 接続の待機中に入出力エラーが発生した場合
  • このソケットを閉じるときに入出力エラーが発生した場合

ここで言う入出力エラーとは、具体的にどういうもので、どのようなコードを書いた時に発生するのでしょうか。
また、socket.close();で例外が発生した時に、恐らくソケットは開いたままなのでどうやって閉じればよいのでしょうか。

ご回答宜しくお願いします。

Java 8 APIドキュメント
ServerSocket (Java Platform SE 8)
Socket (Java Platform SE 8)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

※一部記述がおかしかったので修正しました(11/16 13:30)

Javaに限らずですが、ソケットを使ったプログラムは、TCP/IPレベルでの操作を行っていることになります。
ですので、TCP/IPとそれよりも下層のネットワークレイヤーで起こった何かしらの通信障害があった場合にI/Oエラー(IOException)が発生することが考えられます。
また、クライアント側がJavaプログラムとは限りませんので、その辺も考慮が必要かもしれません。

個別のI/Oエラーの発生条件ですが、いくつか考えられるものを書いてみます。

  • new ServerSocket(30000);では、既にポート30000が使用されている場合など
  • socket = srvSocket.accept();では、コネクションの確立中に不正な通信があった場合など
  • socket.close()では、コネクションの解放処理(FINパケットあたりのやりとり中?)に不正な通信があった場合など

最後に、Socket.closeで例外が起こった場合に確実に切断するというのは、標準APIではできないのではないかと思います。自信はありませんが...
ソースコードを見た感じではSocket自体はクローズ状態にはならないようですので、ダメ元でもう一度Socket.closeを実行してみるのはどうでしょうか。

参考URL:
【要約】Javaネットワークプログラミングの真髄 第3章 「TCPの基礎」 - MajiMeM

投稿2014/11/15 14:00

argius

総合スコア9390

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2014/11/16 02:49

ご回答ありがとうございます。 なるほど、IOExceptionの原因はアプリケーションの実装の問題以外にも、ネットワーク層以下での問題や、物理的な問題(データの損失等)も考えられるんですね。 `Socket.close()`で例外が発生した際に(恐らく開いたまま)、閉じようとするのはやはり難しそうですね。argiusさんの仰る通り、再度`Socket.close()`をしてそれでも例外が出るようだったら、プログラムの強制終了も考えつつコーディングをしていこうと思います。
TaMaMhyu

2014/11/20 00:16

たとえcloseできたとしても、TCPなどはすぐには完全に閉じないと思うので、Java8ならtry-with-resources文でとりあえず自動closeにしておいた方がいいかもしれません。
退会済みユーザー

退会済みユーザー

2014/11/20 09:16

オートクローズ機能は初めて知りました。確かにこちらの構文を利用したほうがよさそうですね。コメントありがとうございます。
guest

0

TaMaMhyuさん
そうですね、今回はその辺は特に触れていなかったので記載しませんでしたが、closeはtry-with-resources(Java6以前ならfinally)でcloseしておいた方が良いですね。

投稿2014/11/20 01:40

argius

総合スコア9390

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問