簡體   English   中英

使用連接構造函數創建的套接字的連接超時是多少?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM