[英]Java socket connection - how to set a timeout when connecting server restarts
[英]What's the connection timeout of a socket created with a connecting constructor?
使用連接構造函數創建的套接字的連接超時是多少?
在Java SE 6中,Socket的以下構造函數將立即連接套接字,而不是在構造之后必須在其上調用connect:
Socket(InetAddress address, int port)
Socket(InetAddress host, int port, boolean stream)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
Socket(String host, int port)
Socket(String host, int port, boolean stream)
Socket(String host, int port, InetAddress localAddr, int localPort)
雖然它很方便,所有Java SE人員創建了500種構造套接字的方法,所以你只需要瀏覽500的列表就可以找到你想要的那種(而不是調用new Socket()
后跟Socket#connect()
),這些構造函數的所有文檔都沒有說明連接超時是什么,或者它們是否/如何調用connect(SocketAddress endpoint, int timeout)
。
也許構造函數docs中關於createSocketImpl
東西暗示了關於超時的東西,或者其他地方的一些文檔說的呢?
任何人都知道這些構造函數的實際連接超時是什么?
背景:好的,假設規范真的很模糊(我認為Java是可移植的?),我試圖弄清楚為什么客戶的代碼會在看似隨機的時候凍結。 我有一些代碼調用一些開源庫來調用其中一個構造函數。 我想知道調用其中一個構造函數是否會使超時無限或很長。 我不知道客戶使用的是什么版本的JDK,所以如果規范在某個地方說出超時,那就太好了。 我想我可以從我的客戶那里獲得JDK版本,但它可能是閉源JDK。 在這種情況下,我可以對他們的SE庫版本中的代碼進行反向工程以找出答案嗎? 難嗎? 我會去監獄嗎?
盡管Java文檔說超時是無限的,但它實際上意味着JVM不會對連接操作施加任何超時,但操作系統可以自由地對任何套接字操作施加超時設置。
因此,實際超時將取決於操作系統的TCP / IP層設置。
一個好的編程習慣是為所有套接字操作設置超時,最好通過配置文件進行配置。 使其可配置的優點是,根據部署環境的網絡負載,可以調整超時,而無需重新構建/重新測試/重新發布整個軟件。
Java規范是假的。 它沒有說明任何構造函數的超時是什么,因此實現可以將超時設置為0.000000000001納秒並且仍然是正確的。 更多:vm實現甚至沒有遵守非有限超時(如此處所示)所以看起來像spec甚至不重要因為沒有人跟着它。
結論:您必須閱讀客戶JVM的閉源二進制文件(可能是非法的,但您必須做您必須做的事情),也是OS套接字文檔。
查看code of Socket in OpenJDK 6-b14
,您可以看到這些構造函數調用connect(socketAddress, 0)
,這意味着無限超時值。
根據消息來源(我在這里看1.5_13,但應該沒有區別),不同的Socket構造函數都調用Socket(SocketAddress, SocketAddress, boolean)
,定義如下:
private Socket(SocketAddress address, SocketAddress localAddr,
boolean stream) throws IOException {
setImpl();
// backward compatibility
if (address == null)
throw new NullPointerException();
try {
createImpl(stream);
if (localAddr == null)
localAddr = new InetSocketAddress(0);
bind(localAddr);
if (address != null)
connect(address);
} catch (IOException e) {
close();
throw e;
}
}
connect(SocketAddress)
定義為
public void connect(SocketAddress endpoint) throws IOException {
connect(endpoint, 0);
}
因此,無限超時(如@Keppil已經說明的那樣)。
Socket類自Java 1.0以來就存在,但在那時,它只能創建立即連接的套接字,並且無法指定連接超時。 從Java 1.4開始,可以創建未連接的套接字,然后使用connect方法指定超時。 我假設有人只是忘了澄清“舊”構造函數的文檔,指定它們仍然在沒有顯式超時的情況下運行。
帶有timeout參數的connect方法的文檔讀取“超時為零被解釋為無限超時”。 這實際上也是不正確的,因為它只意味着Java VM沒有暗示超時。 即使超時為0,連接操作仍可能在操作系統的TCP / IP堆棧中超時。
它取決於平台,但大約需要一分鍾。 connect()的Javadoc聲明它是無限的是不正確的。 另請注意,connect()timeout參數只能用於降低默認值,而不能增加默認值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.