Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7116990

(spec) Socket.connect(addr,timeout) not clear if IOException because of TCP timeout

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P3 P3
    • 26
    • 7
    • core-libs
    • generic
    • generic

      SYNOPSIS
      --------
      Long Socket.connect() timeouts not honored

      OPERATING SYSTEM(S)
      -------------------
      Windows (tested on Windows XP)
      Linux (tested on Ubuntu)

      FULL JDK VERSION(S)
      -------------------
      All (1.4.2, 5.0, 6 and 7)

      PROBLEM DESCRIPTION
      -------------------
      Timeout values passed into Socket.connect() are not always honoured. Specifically, values larger than 21 seconds are not honoured on Windows and Linux - the connection attempt just times out after 21 seconds.

      It's quite possible that the OS is abandoning the connection attempt. On Windows, the registry setting TcpMaxConnectRetransmissions seems to govern the behaviour of the OS:

      --------
      TcpMaxConnectRetransmissions
      Key: Tcpip\Parameters
      Value Type: REG_DWORD - Number
      Valid Range: 0 - 0xFFFFFFFF
      Default: 2
      Description: This parameter determines the number of times that TCP retransmits a connect request (SYN) before aborting the attempt. The retransmission timeout is doubled with each successive retransmission in a particular connect attempt. The initial timeout value is three seconds.
      --------
      http://support.microsoft.com/kb/314053

      The two retries would result in an overall timeout of 21 seconds (3 + 6 +12 = 21).

      On Linux, the equivalent OS setting appears to be tcp_synack_retries or
      tcp_syn_retries, but these default to 5, which should give an OS timeout of 3 minutes. However, on Linux I see the same limited timeout as Windows - 21 seconds.

      So this behaviour may be caused by the OS, but shouldn't Java respect the timeout passed into the Socket.connect() method regardless? There doesn't seem to be any reason why the connect() method couldn't continue to retry after the first OS connection attempt times out.

      REPRODUCTION INSTRUCTIONS
      -------------------------
      1. javac Timeout.java
      2. java Timeout 30000

      Expected output:
      Timed out after 30.000 seconds (value may deviate from 30s slightly)

      Observed output:
      Timed out after 21.672 seconds (value is approximately 21 seconds)

      TESTCASE
      --------
      import java.net.*;

      class Timeout {
          public static void main(String[] args) throws Exception {
              if (args.length != 1) {
                  System.out.println("Usage: java Timeout [timeout (ms)]");
                  System.exit(1);
              }

              int timeout = Integer.parseInt(args[0]);
              long startTime = 0;
              long endTime = 0;
             
              Socket s = new Socket();
              // Create a non-existent endpoint to guarantee a connection timeout
              InetSocketAddress endpoint = new InetSocketAddress(InetAddress.getByName("10.0.0.1"), 55555);

              try {
                  startTime = System.currentTimeMillis();
                  s.connect(endpoint, timeout);
              } catch (Exception e) {
                  endTime = System.currentTimeMillis();
                  System.out.println("Timed out after " + ((float)(endTime - startTime))/1000 + " seconds");
              }
          }
      }

      WORKAROUND
      ----------
      On Windows, set the registry key TcpMaxConnectRetransmissions to a value high enough to allow the specified timeout.

            jpai Jaikiran Pai
            dkorbel David Korbel (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: