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

reuseAddress(true) dosen't work. throws address already in use BindException

XMLWordPrintable

    • x86_64
    • windows_10

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10 Pro[Version 10.0.19044 Build 19044]
      Java 17


      A DESCRIPTION OF THE PROBLEM :
      When reuseAddress(true) is set on both client and server socket and then bound its works the first time but when running the client application an 2nd time throws address already in use exception

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) Open an server socket on a separate JVM[Process]. set reuseAddress(true) on it before binding

      2) Open an client socket connecting to this server on a separate JVM[Process.] set reuseAddress(true) on it before binding and connecting

      3) Run the client process an 2nd time and it throws the exception

      Procedure.

      Before running the program we use netstat -aon | findstr in windows cmd to check for sockets running on an specific port

      server=running on port 2500
      client bounded to port 5000

      netstat -aon | findstr 2500
      <Nothing>
      netstat -aon | findstr 2500
      <Nothing>

      a) We then run the server and check for its status on port 2500

      netstat -aon | findstr 2500
       TCP 192.168.1.2:2500 0.0.0.0:0 LISTENING 7676

      b) We run the client and after it exits check the port 5000
         netstat -aon | findstr 5000
           TCP 192.168.1.2:5000 192.168.1.2:2500 TIME_WAIT 0

      c) We also check the server again
            netstat -aon | findstr 2500
          TCP 192.168.1.2:2500 0.0.0.0:0 LISTENING 7676
          TCP 192.168.1.2:5000 192.168.1.2:2500 TIME_WAIT 0

      We can see the server is holding on to the client socket and the client socket is in TIME_WAIT state. The documentation of setReuseAddress clearly states

      "When a TCP connection is closed the connection may remain in a timeout state for a period of time after the connection is closed (typically known as the TIME_WAIT state or 2MSL wait state). For applications using a well known socket address or port it may not be possible to bind a socket to the required SocketAddress if there is a connection in the timeout state involving the socket address or port.

      Enabling SO_REUSEADDR prior to binding the socket using bind(SocketAddress) allows the socket to be bound even though a previous connection is in a timeout state."

      Inspite of what it says running the client a 2nd time produces an bind exception address already in use

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      No error. Sockets should be able to reuse the address immediatly after closing without waiting 4 minutes for the socket in TIME_WAIT state to be removed
      ACTUAL -
      java.net.BindException: Address already in use: connect
      at java.base/sun.nio.ch.Net.connect0(Native Method)
      at java.base/sun.nio.ch.Net.connect(Net.java:579)
      at java.base/sun.nio.ch.Net.connect(Net.java:568)
      at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:588)
      at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
      at java.base/java.net.Socket.connect(Socket.java:633)
      at java.base/java.net.Socket.connect(Socket.java:583)

      ---------- BEGIN SOURCE ----------
      Server. Run as an separate process

       public static void main(String[] args)throws Exception
       {
        try(ServerSocket server=new ServerSocket())
        {
         server.setReuseAddress(true);
         
         server.bind(new InetSocketAddress(InetAddress.getLocalHost(),2500));
        
         while(true)
         {
          try(Socket client=server.accept())
          {
           //simple wait before closing
           Thread.sleep(2000);
          }
         }
        }
       }

      Client. Run as an separate process

      public static void main(String[] args)throws Exception
       {
        try(Socket client=new Socket())
        {
         client.setReuseAddress(true);
         
         client.bind(new InetSocketAddress(InetAddress.getLocalHost(),5000));
         
         client.connect(new InetSocketAddress(InetAddress.getLocalHost(),2500));
        }
       }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      only way to terminate the client socket is client.setSoLinger(true,0) which crashes the server so is not an optimal solution

      FREQUENCY : always


        1. Client.java
          0.5 kB
        2. Server.java
          0.8 kB

            djelinski Daniel Jelinski
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: