JDK-4476369 : MulticastSocket.setReuseAddress(true) is ignored on windows platforms
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 1.4.0
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_95
  • CPU: x86
  • Submitted: 2001-06-29
  • Updated: 2001-06-29
  • Resolved: 2001-06-29
Related Reports
Duplicate :  
Description

Name: dfR10049			Date: 06/29/2001


Javadoc states about java.net.DatagramSocket.setReuseAddress(boolean on):

    Enable/disable SO_REUSEADDR. The SO_REUSEADDR socket option affects the
    bind() operation and serves 2 main different purposes: 
      o Allows completely duplicate bindings (same address and port) on multicast
        sockets, in which case when a datagram is received for one of these multiply
        bound sockets, one copy of the the datagram is delivered to each matching socket.
      o Allows a single process to bind the same port to multiple sockets as long as each
        bind specifies a different local IP address. 

    Note that setReuseAddress(true) will only be enabled on the socket if the underlying
    network implementation can guarantee that this can be done safely. Thus enabling
    SO_REUSEADDR should be considered as a hint and applications that wish to verify
    wether SO_REUSEADDR has been enabled should call getReuseAddress(). 

So if getReuseAddress() returns true for MulticastSocket then bind() operation
should be allowed even if port is already in use. This works on solaris,
but does not work on win98 and win2000

This is the test demonstrating the bug:
------------------------------------------------------------------
import java.net.*;

public class DSTest {

    public static void main (String args[]) {


        int port = Integer.decode(args[0]).intValue();

        MulticastSocket ms1 = null;
        MulticastSocket ms2 = null;
        try {
    
            InetAddress localAddr = InetAddress.getLocalHost();
            InetSocketAddress addr = new InetSocketAddress(localAddr, port);
       
            ms1 = new MulticastSocket(null);
            try {
                ms1.bind(addr);
            } catch (SocketException e) {
                System.out.println("cannot bind first socket to " + addr
                        + " unexpected " + e);
                return;
            }
         
            ms2 = new MulticastSocket(null);
            ms2.setReuseAddress(true);
            if (!ms2.getReuseAddress()) {
                System.out.println("Cannot check: " 
                    + " safety for SO_REUSEADDR option is not guaranteed");
                return;
            }
        
            System.out.println("getReuseAddress(): " + ms2.getReuseAddress());
            try {
                ms2.bind(addr);
            } catch (SocketException e) {
                System.out.println("cannot bind second socket to " + addr
                        + " unexpected " + e);
                return;
            }
        
            System.out.println("Test passed");
        } catch (Exception e) {
            System.out.println("Unexpected: " + e);
            e.printStackTrace(System.out);
        }

    }
    
}

---------------------------------------------------------------------
output from the test:

on Solaris:
#> java DSTest 12345
getReuseAddress(): true
Test passed

on win98 and win2000:
#> java DSTest 12345
getReuseAddress(): true
cannot bind second socket to vento/192.168.205.171:12345 unexpected java.net.BindException: Address already in use: Cannot bind

======================================================================

Comments
EVALUATION We have a general problem with SO_REUSEADDR that we plan to fix for beta-refresh. The reason why the bind fails in this test case is that we disable SO_REUSEADDR on the original socket when you bind to a specific address. If the getReuseAddress test were done after the bind this would be visible. We will use 4476378 to track the Windows SO_REUSEADDR issues. alan.bateman@ireland 2001-06-29
29-06-2001