2010-09-13 55 views
24

我正在使用Java套接字客戶端。在服務器仍然連接到我的客戶端但它不會對我的消息發送響應的情況下 - 我最終會得到讀取超時異常。如何連接和關閉插座?

在這種情況下,我想測試,看看我是否應該重新連接我的套接字或只是讓它重新使用它。

我用這個條件:

if (!socket.isConnected() || socket.isClosed() || !socket.isBound()) { 
    try { 
     socket.close(); 
    } catch (IOException e1) { 
    } 
    // Wait on a new connection 
    socket = connectSocket(.....); 
} 

但我似乎總是重新連接。當我登錄的布爾屬性的值,我看到:

連接:真正的關閉:真正的約束:真

怎樣纔可以連接並關閉?

TIA

+0

方法調用不是原子的......也許另一個線程正在關閉isConnected()和isClosed()調用之間的套接字?也許首先同步套接字對象? – Powerlord 2010-09-13 14:02:24

+0

如果您只是將「isConnected()」和「isClosed()'的檢查順序顛倒過來,就很容易測試。 – 2010-09-13 14:15:23

回答

66

This thread了關於該議題的一些有益的討論。事實證明,Socket.isConnected如果(曾經)成功連接,則返回true。

從上面的線:

當您使用Socket(),你似乎都忽略了, Socket.isConnected()告訴你Socket.connect()是否已被稱爲 與否。對於isClosed()close()也是如此。

混淆這些方法從混淆 插座,這是應用程序的控制下的狀態下,與整體連接,這是所述協議的控制下的狀態結果 。 isConnected()isClosed()告訴你對套接字做了什麼。 除了讀取和寫入之外,沒有任何API用於確定連接的狀態。

的文檔說:

返回true,如果將套接字成功地連接到服務器

,而不是作爲一個也許會想到「返回true,如果套接字連接到服務器「。

行爲可以通過查看插座的來源得到證實:

public boolean isConnected() { 
    // Before 1.3 Sockets were always connected during creation 
    return connected || oldImpl; 
} 

你也可以運行這個小測試片段:

Socket s = new Socket(); 

System.out.println("isConnected: " + s.isConnected() + 
        " isBound: "  + s.isBound() + 
        " isClosed: " + s.isClosed()); 

s.connect(new InetSocketAddress("google.com", 80)); 

System.out.println("isConnected: " + s.isConnected() + 
        " isBound: " + s.isBound() + 
        " isClosed: " + s.isClosed()); 

s.close(); 

System.out.println("isConnected: " + s.isConnected() + 
        " isBound: " + s.isBound() + 
        " isClosed: " + s.isClosed()); 

它打印:

isConnected: false isBound: false isClosed: false 
isConnected: true isBound: true isClosed: false 
isConnected: true isBound: true isClosed: true 

我必須說,這個文檔在這方面還不是很清楚,而且方法名稱有點不明確isleading。

+11

+1布拉沃!很好的答案! – 2010-09-13 14:24:53

+2

謝謝。現在,我很清楚。 – sproketboy 2010-09-13 14:26:41

+0

破碎的鏈接,但從引用看來,它似乎已經從這裏或在Sun/Oracle Java論壇的答案中解除了holus-bolus,其中很多都是由我來完成的。 – EJP 2017-07-06 01:35:05