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

Socket(String host, int port) creates a socket connected to itself

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Won't Fix
    • Icon: P4 P4
    • None
    • 5.0
    • core-libs
    • x86
    • linux

      FULL PRODUCT VERSION :
      java -version
      java version "1.5.0_05"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
      Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_05-b05, mixed mode)

      java -version
      java version "1.6.0-beta2"
      Java(TM) SE Runtime Environment (build 1.6.0-beta2-b86)
      Java HotSpot(TM) Client VM (build 1.6.0-beta2-b86, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      uname -a
      Linux dbserv 2.6.17.6 #1 SMP Thu Jul 20 09:57:11 CEST 2006 x86_64 x86_64 x86_64
      GNU/Linux

      uname -a
      Linux sayonara 2.6.17.13 #2 Wed Sep 13 12:06:56 CEST 2006 i686 i686 i386 GNU/Lin
      ux


      A DESCRIPTION OF THE PROBLEM :
      Attempt to connect to a unused port on the localhost can unexpectedly succeed, resulting in a socket connected to itself.

      The bug shows itself in the following scenario:

      try
      {
          String host = "localhost";
          int port = 60666;

          Socket socket = new Socket(host, port);

          // connected, the socket can be used
          
      } catch(IOException e) {
          // not connected
      }

      If the port 60666 in the above example is free, i.e. no one is listening on it, the connection attempt must fail. However, occasionally (on my system approximately 50 times per 1 million tries) connection is established!

      The resulting socket has equal local and remote addresses. Data written to the output stream of the socket can be read from the input stream. The cause is obvious: since port number 60666 is free, it can occasionally be picked it up for the local socket address. If we manually bind to the port, as in the Test2 code below, problem becomes 100% reproducible.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Please see Test1 and Test2 code below.

      The Test1 code reproduces the original bug (can take a few minutes to run).
      The Test2 is a shortcut to create a self-connected socket.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I expect Test1 to run endless, Test2 to print out an exception stack trace.

      ACTUAL -
      On the Linux platform, a self-connected socket is created.

      Test1 output (iter number may vary):
      ---------------------------------------------------------------------------
      On iter 34848 connected to non-running server, localaddr='/127.0.0.1:60669'
      Connected to itself!
      ---------------------------------------------------------------------------

      Test2 output:
      ---------------------------------------------------------------------------
      Bound to localaddr='/127.0.0.1:60668'
      connected to remoteaddr='localhost/127.0.0.1:60668'
      Connected to itself!
      ---------------------------------------------------------------------------

      The bug is Linux-specific.

      I have performed the tests in Windows and Sun environments. Here is Test2 output on Windows XP:
      ---------------------------------------------------------------------------
      java.net.ConnectException: Connection refused: connect
      at java.net.PlainSocketImpl.socketConnect(Native Method)
      at java.net.PlainSocketImpl.doConnect(Unknown Source)
      at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
      at java.net.PlainSocketImpl.connect(Unknown Source)
      at java.net.SocksSocketImpl.connect(Unknown Source)
      at java.net.Socket.connect(Unknown Source)
      at java.net.Socket.connect(Unknown Source)
      at Test2.main(Test2.java:17)
      ---------------------------------------------------------------------------

      Here is Test2 output on Sun:
      ---------------------------------------------------------------------------
      java.net.NoRouteToHostException: Cannot assign requested address
              at java.net.PlainSocketImpl.socketConnect(Native Method)
              at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
              at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
              at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
              at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
              at java.net.Socket.connect(Socket.java:507)
              at java.net.Socket.connect(Socket.java:457)
              at Test2.main(Test2.java:17)
      ---------------------------------------------------------------------------
      The meaning of the last exception is unobvious, to say the less ;-) but no self-connected socket is created.


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      Test1.java:
      ---------------------------------------------------------------------------
      import java.io.IOException;
      import java.net.Socket;

      public class Test1
      {
          public static void main(String[] args)
          {
              long i = 0;
              
              String host = "localhost";
              int port = 60669;
              
              Socket socket;
              while(true)
              {
                  i++;
                  try
                  {
                      socket = new Socket(host, port);
                      
                      System.err.println("On iter " + i
                                  + " connected to non-running server, localaddr='"
                                  + socket.getLocalSocketAddress() + "'");
                      
                      if (socket.getLocalSocketAddress()
                                 .equals(socket.getRemoteSocketAddress()))
                      {
                          System.err.println("Connected to itself!");
                      }
                      break;
                  } catch (IOException e) {
                      // OK
                  }
              }
          }
      }
      ---------------------------------------------------------------------------

      Test2.java:
      ---------------------------------------------------------------------------
      import java.io.IOException;
      import java.net.InetSocketAddress;
      import java.net.Socket;

      public class Test2
      {
          public static void main(String[] args)
          {
              String host = "localhost";
              int port = 60668;
              
              try
              {
                  Socket socket = new Socket();
                  
                  socket.bind(new InetSocketAddress(port));
                  socket.connect(new InetSocketAddress(host, port));
                  
                  System.err.println("Bound to localaddr='"
                                                             + socket.getLocalSocketAddress() + "'");
                  System.err.println("connected to remoteaddr='"
                                                             + socket.getRemoteSocketAddress() + "'");
                  
                  if (socket.getLocalSocketAddress()
                                              .equals(socket.getRemoteSocketAddress()))
                  {
                      System.err.println("Connected to itself!");
                  }
                  
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
      ---------------------------------------------------------------------------

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Check socket after connection, like:
      [...]
      Socket socket = new Socket(host, port);
      if (socket.getLocalSocketAddress()
                   .equals(socket.getRemoteSocketAddress()))
      {
          throw new IOException("Localy bound to the server port");
      }
      [...]

            msheppar Mark Sheppard
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: