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でから入手できます。