Search code examples
javaserversockettime-wait

Java server socket doesn't reuse address


I am using a server socket in linux and I need to close it and reopen before the time_wait TCP status expires. I set the reuse address option of the server socket before the binding but it still throws a BindException. I also tried this http://meteatamel.wordpress.com/2010/12/01/socket-reuseaddress-property-and-linux/ but it still doesn't work.

To open a server socket i use:

ServerSocket ss = new ServerSocket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(12345));

and to close:

ss.close();

The "Address already in use" BindException is throwed at the bind call.

This code generates the exception:

for (int i = 0; i < 2; i++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    final ServerSocket ss = new ServerSocket();
                    ss.setReuseAddress(true);
                    ss.bind(new InetSocketAddress(12345));
                    Socket s = ss.accept();
                    System.out.println((char) s.getInputStream().read());
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        Thread.sleep(500);
        Socket s = new Socket("localhost", 12345);
        s.getOutputStream().write('c');
    }

Solution

  • You set reuse before binding not after you get an exception.

    ServerSocket ss = new ServerSocket(); // don't bind just yet
    ss.setReuseAddress(true);
    ss.bind(new InetSocketAddress(12345)); // can bind with reuse= true
    

    This runs without error on Windows 7 and RHEL 5.x

    for (int i = 0; i < 1000; i++) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    final ServerSocket ss = new ServerSocket();
                    ss.setReuseAddress(true);
                    ss.bind(new InetSocketAddress(12345));
                    Socket s = ss.accept();
                    System.out.println((char) s.getInputStream().read());
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        Thread.sleep(50);
        Socket s = new Socket("localhost", 12345);
        s.getOutputStream().write('c');
        t.join();
    }