我曾經遇到過socket通信的問題Linux系統上的過程中永遠掛起,其通信過程是象下面這樣:客戶端發送郵件向服務器做一個計算任務,任務完成後等待來自服務器的結果消息。ObjectInputStream.readObject()socket通信
但是,如果任務花費很長時間(例如大約40分鐘),則客戶端會掛起等待結果消息,即使從服務器端,結果消息已被寫入套接字以響應客戶端,但是如果任務花費很少時間,例如一分鐘,它通常可以收到結果消息。另外,這個問題只發生在客戶環境中,通信過程在我們的測試環境中正常運行。
我一直懷疑的原因這個問題是插座的默認超時值是客戶環境和測試環境之間的不同,但後續的值是在這兩個環境相同,客戶端和服務器。
getSoTimeout:0
getReceiveBufferSize:43690
getSendBufferSize:8192
getSoLinger:-1
getTrafficClass:0
getKeepAlive:false
getTcpNoDelay:false
在客戶端的代碼是這樣的:
Message msg = null;
ObjectInputStream in = client.getClient().getInputStream();
//if no message readObject() will hang here
while (true) {
try {
Object recObject = in.readObject();
System.out.println("Client received msg.");
msg = (Message)recObject;
return msg;
}catch (Exception e) {
e.printStackTrace();
return null;
}
}
代碼上服務器都喜歡,
ObjectOutputStream socketOutStream = getSocketOutputStream();
try {
MessageJobComplete msgJobComplete = new MessageJobComplete(reportFile, outputFile);
socketOutStream.writeObject(msgJobComplete);
}catch(Exception e) {
e.printStackTrace();
}
爲了解決這個問題,我已經添加了沖洗和復位方法,但問題依然存在:
ObjectOutputStream socketOutStream = getSocketOutputStream();
try {
MessageJobComplete msgJobComplete = new MessageJobComplete(reportFile, outputFile);
socketOutStream.flush();
logger.debug("AbstractJob#reply to the socket");
socketOutStream.writeObject(msgJobComplete);
socketOutStream.reset();
socketOutStream.flush();
logger.debug("AbstractJob#after Flush Reply");
}catch(Exception e) {
e.printStackTrace();
logger.error("Exception when sending MessageJobComplete."+e.getMessage());
}
所以,有誰知道我應該怎樣做才能解決這個問題。 我猜的原因是環境設置,但我不知道環境因素會影響套接字通信?
並採用TCP/IP protocal交流插座,問題與長時間工作的關係,所以什麼樣的價值觀有關TCP會影響socket通信的超時?
我有關日誌的分析後,我發現該消息被寫入到插座後,有沒有異常拋出/捕獲。但總是在15分鐘後,服務器端的objectInputStream.readObject()代碼片段中有例外,它用於接受來自客戶端的請求。但是,socket.getSoTimeout值爲0,因此引發超時異常是非常奇怪的。
{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)
那麼爲什麼Connection Timed out異常被拋出?
如果客戶端沒有收到,它的服務器可能沒有發送。我會確認你看到客戶端沒有收到的發送對象的日誌消息。 – 2012-01-10 07:57:14
謝謝,但是日誌顯示對象已經發送,並且沒有檢測到任何異常,只是客戶端掛起,你知道如何檢查嗎? {2012-01-09 19:28:16,416} DEBUG AbstractJob#回覆socket {2012-01-09 19:28:16,422} DEBUG AbstractJob#沖洗後回覆 – 2012-01-11 00:53:35
printStackTrace不會出現在日誌中,它們是寫入控制檯。如果您沒有將控制檯寫入文件,我會確保將異常寫入日誌。 – 2012-01-11 07:23:31