DatagramSocket and MulticastSocket have different supported options. But option set is cached depends on which socket's method was called firstly and then returned for both DatagramSocket and MulticastSocket.
Example 1. MulticastSocket's set is returned for DatagramSocket:
import java.io.IOException;
import java.net.*;
public class Test1 {
public static void main(String[] args) throws IOException {
System.out.println((new MulticastSocket()).supportedOptions());
System.out.println((new DatagramSocket()).supportedOptions());
}
}
Output:
[IP_MULTICAST_IF, SO_SNDBUF, IP_MULTICAST_LOOP, IP_TOS, IP_MULTICAST_TTL, SO_REUSEADDR, SO_RCVBUF]
[IP_MULTICAST_IF, SO_SNDBUF, IP_MULTICAST_LOOP, IP_TOS, IP_MULTICAST_TTL, SO_REUSEADDR, SO_RCVBUF]
Example2 DatagramSocket's set is returned for MulticastSocket:
import java.io.IOException;
import java.net.*;
public class Test2 {
public static void main(String[] args) throws IOException {
System.out.println((new DatagramSocket()).supportedOptions());
System.out.println((new MulticastSocket()).supportedOptions());
}
}
Output:
[SO_SNDBUF, IP_TOS, SO_REUSEADDR, SO_RCVBUF]
[SO_SNDBUF, IP_TOS, SO_REUSEADDR, SO_RCVBUF]
Cause:
DatagramSocket's method supportedOptions() is used for both DatagramSocket and MulticastSocket as second one inherits from the first one.
public Set<SocketOption<?>> supportedOptions() {
synchronized(DatagramSocket.class) {
if (optionsSet) {
return options;
}
try {
DatagramSocketImpl impl = getImpl();
options = Collections.unmodifiableSet(impl.supportedOptions());
} catch (IOException e) {
options = Collections.emptySet();
}
optionsSet = true;
return options;
}
}
Method cashes options from the first call and doesn't check actual socket type.
Suggested fix:
Implement supportedOptions() method in MulticastSocket or add socket type check.