1. 序章

このチュートリアルでは、Javaソケットプログラミングのタイムアウト例外に焦点を当てます。 私たちの目標は、これらの例外が発生する理由とその処理方法を理解することです。

2. Javaソケットとタイムアウト

ソケットは、2つのコンピューターアプリケーション間の論理リンクの1つのエンドポイントです。 つまり、アプリケーションがネットワークを介してデータを送受信するために使用する論理インターフェイスです。

一般に、ソケットはIPアドレスとポート番号の組み合わせです。 各ソケットには、サービスの識別に使用される特定のポート番号が割り当てられています。

接続ベースのサービスは、TCP-ベースのストリームソケットを使用します。 このため、 Javaは、クライアント側プログラミング用のjava.net.Socketクラスを提供します。 一方、サーバー側のTCP / IPプログラミングでは、java.net.ServerSocketクラスを使用します。

別のタイプのソケットは、コネクションレス型サービスに使用されるUDP-ベースのデータグラムソケットです。 Javaは、UDP操作用のjava.net.DatagramSocketを提供します。 ただし、このチュートリアルでは、TCP/IPソケットに焦点を当てます。

3. 接続がタイムアウトしました

3.1. 「接続タイムアウト」とは何ですか?

クライアント側からサーバーへの接続を確立するために、ソケットコンストラクターが呼び出され、ソケットオブジェクトがインスタンス化されます。 コンストラクターは、リモートホストアドレスとポート番号を入力引数として受け取ります。 その後、指定されたパラメータに基づいてリモートホストへの接続を確立しようとします。

接続が成功するまで、この操作は他のすべてのプロセスをブロックします。 ただし、一定時間後に接続が成功しなかった場合、プログラムはConnectionExceptionをスローして「接続がタイムアウトしました」というメッセージを表示します。

java.net.ConnectException: Connection timed out: connect

サーバー側からは、ServerSocketクラスは着信接続要求を継続的にリッスンします。 ServerSocketは接続要求を受信すると、accept()メソッドを呼び出して、新しいソケットオブジェクトをインスタンス化します。 同様に、このメソッドも、リモートクライアントとの接続が正常に確立されるまでブロックします。

TCPハンドシェイクが完了していない場合、接続は失敗したままになります。 その結果、プログラムは、新しい接続の確立中にエラーが発生したことを示すIOExceptionをスローします

3.2. なぜ発生するのですか?

接続タイムアウトエラーには、いくつかの理由が考えられます。

  • リモートホスト上の特定のポートをリッスンしているサービスはありません
  • リモートホストは接続を受け入れていません
  • リモートホストは利用できません
  • 遅いインターネット接続
  • リモートホストへの転送パスはありません

3.3. それをどのように扱うか?

ブロッキング時間には制限がなく、プログラマーはクライアントとサーバーの両方の操作のタイムアウトオプションを事前に設定できます。 クライアント側では、最初に空のソケットを作成します。 その後、 connect(SocketAddress endpoint、int timeout)メソッドを使用して、タイムアウトパラメーターを設定します。

Socket socket = new Socket(); 
SocketAddress socketAddress = new InetSocketAddress(host, port); 
socket.connect(socketAddress, 30000);

タイムアウトの単位はミリ秒であり、0より大きくする必要があります。 ただし、メソッド呼び出しが戻る前にタイムアウトが期限切れになると、SocketTimeoutExceptionがスローされます。

Exception in thread "main" java.net.SocketTimeoutException: Connect timed out

サーバー側では、setSoTimeout(int timeout)メソッドを使用してタイムアウト値を設定します。 timeout 値は、 ServerSocket.accept()メソッドがブロックする期間を定義します。

ServerSocket serverSocket = new new ServerSocket(port);
serverSocket.setSoTimeout(40000);

同様に、 timeout の単位はミリ秒単位で、0より大きくする必要があります。 メソッドが戻る前にタイムアウトが経過すると、SocketTimeoutExceptionがスローされます。

時々、ファイアウォールはセキュリティ上の理由のために特定のポートをブロックします。 その結果、クライアントがサーバーへの接続を確立しようとすると、「接続タイムアウト」エラーが発生する可能性があります。 したがって、ファイアウォール設定をチェックして、ポートをサービスにバインドする前に、ポートがブロックされているかどうかを確認する必要があります。

4. タイムアウトを読む

4.1. 「読み取りタイムアウト」とは何ですか?

InputStreamのread()メソッド呼び出しは、ソケットからのデータバイトの読み取りが完了するまでブロックします。操作は、ソケットから少なくとも1データバイトを読み取るまで待機します。 ただし、メソッドが不特定の時間後に何も返さない場合、「Readtimedout」エラーメッセージとともにInterrupedIOExceptionがスローされます。

java.net.SocketTimeoutException: Read timed out

4.2. なぜ発生するのですか?

クライアント側から見ると、サーバーが応答して情報を送信するのに時間がかかる場合は「読み取りタイムアウト」エラーが発生します。 これは、インターネット接続が遅いか、ホストがオフラインであることが原因である可能性があります。

サーバー側から見ると、サーバーが事前設定されたタイムアウトと比較してデータの読み取りに長い時間がかかる場合に発生します。

4.3. それをどのように扱うか?

TCPクライアントとサーバーの両方で、socketInputStream.read()メソッド がsetSoTimeout(int timeout)メソッドでブロックする時間を指定できます。

Socket socket = new Socket(host, port);
socket.setSoTimeout(30000);

ただし、メソッドが戻る前にタイムアウトが経過すると、プログラムはSocketTimeoutExceptionをスローします。

5. 結論

この記事では、Javaソケットプログラミングのタイムアウト例外を調べ、それらを処理する方法を学びました。

いつものように、コードはGitHubから入手できます。