2012-01-18 384 views
2

這個SocketException拋出ObjectInputStream.readObject()方法,是什麼原因導致這個excetpion?此外,客戶端和服務器套接字的soTimeout值均爲0,並且KeepAlive值爲false。什麼原因導致:java.net.SocketException:連接超時,不是SocketTimeoutException

{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文件,如果該方法被設置無零值,則次期滿時,僅SocketTimeoutException被拋出,而不是SocketException:連接超時,於是,這異常不應該與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(); 

回答

3

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異常:連接在22點54超時,以後約15分鐘從的writeObject調用。

所以我們可以得出這樣的結論:這個異常是由於可能tcp連接由於很長時間(大約30分鐘)沒有流量而不可用,同時沒有socket.close()方法被調用來關閉套接字在實例中,然後拋出這個異常。

所以爲了避免這種異常,你應該使用方法Socket.setKeepAlive()方法保持連接的活動狀態,儘管你可能沒有使用方法setTimeout(),這意味着要求套接字無限制地接收;

或在您的應用程序中應用心跳機制。

相關問題