7

この SocketException は ObjectInputStream.readObject() メソッドでスローされますが、この例外の原因は何ですか? また、クライアントとサーバーのソケットの soTimeout の値は両方とも 0 で、KeepAlive の値は false です。

{2012-01-09 17:44:13,908} ERROR java.net.SocketException: Connection timed out
 at java.net.SocketInputStream.socketRead0(Native Method)
 at java.net.SocketInputStream.read(SocketInputStream.java:146)
 at sun.security.ssl.InputRecord.readFully(InputRecord.java:312)
 at sun.security.ssl.InputRecord.read(InputRecord.java:350)
 at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:809)
 at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:766)
 at sun.security.ssl.AppInputStream.read(AppInputStream.java:94)
 at sun.security.ssl.AppInputStream.read(AppInputStream.java:69)
 at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2265)
 at java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInputStream.java:2558)
 at    java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2568)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1314)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)

setSoTimeout メソッドに関する JAVA API ドキュメントから、このメソッドがゼロ以外の値に設定されている場合、時間切れになると、SocketException:Connection タイムアウトではなく SocketTimeoutException のみがスローされるため、この例外は setSotimeoutMethod とは関係ありません。 .

public void setSoTimeout(int timeout)  throws SocketException
 Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. With this 
 option set to a non-zero timeout, a read() call on the InputStream associated with 
 this Socket will block for only this amount of time. If the timeout expires, a 
 java.net.SocketTimeoutException is raised, though the Socket is still valid. The 
option must be enabled prior to entering the blocking operation to have effect. The 
timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.

しかし、PlainSocketImpl(ここではSSLSocketImpl).getTimeout()で返された値をsetSoTimeout()メソッドで転送するという、やはりかなり変なメソッドです。

 SocketInputStream.socketRead0(FileDescriptor fd, byte b[], int off, int len, int timeout)  
  the timeout value is passed in the constructor of  SocketInputStream:SocketInputStream(PlainSocketImpl impl) throws IOException {}
  timeout = impl.getTimeout();
4

1 に答える 1

5

java.net.SocketException: 接続タイムアウト例外は setTimeout メソッドとは関係がなく、SocketTimedoutException とのみ関係があります。

以下のように、tcpdump によってキャプチャされたメッセージ トレースから:

NO.            Time       Source Destination Protocol Info
14845 2012-02-07 22:37:46 10.*   10.*        DNP 3. len=1,from 52156 to 29466,ACK 
14846 2012-02-07 22:37:46 21.*   10.*        DNP 3. len=1,from 54562 to 50276,ACK
14848 2012-02-07 22:37:46 32.*   10.*        DNP 3. [TCP Restransmission] len=1,from from 52156 to 29466,ACK 
……(7 times retransmission) 
14849 2012-02-07 22:37:47 10.*   10.*        DNP 3. [TCP Restransmission] len=1,from from 52156 to 29466,ACK

このログは java.net.SocketException: Connection timed out at 22:54 をスローしますが、writeObject が呼び出されてから約 15 分後です。

したがって、この例外は、長時間 (約 30 分) トラフィックがないために tcp 接続が使用できなかった可能性があり、その間にソケットを閉じるために呼び出された socket.close() メソッドがないことが原因であると結論付けることができます。この例外がスローされました。

したがって、この例外を回避するには、メソッド Socket.setKeepAlive() を使用して接続を維持する必要がありますが、メソッド setTimeout() を使用していない可能性があります。

または、アプリケーションにハートビート メカニズムを適用します。

于 2012-02-09T06:33:09.967 に答える