On OS X, when creating a server socket on a specific port for all interfaces, a new server socket can bind to localhost
with the same port and accept connections.
I would expect the binding to localhost
to fail, as it does when trying the same in Linux (I tried on Ubuntu specifically).
The behavior on OS X is weird to me, because client connections to localhost
work when listening on all interfaces, but a new server can bind localhost
on the same port and accept new connections, instead of the first listener.
How can a socket listen on all interfaces and also prevent other sockets from binding to localhost
with the same port on OS X?
The following test passes on Mac and fails on Ubuntu, but should fail on both.
import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.ServerSocket;
public class MinimalTest {
@Test
public void listenOnAllInterfacesAndLocalhost() throws IOException {
final int port = 12340;
try (ServerSocket allInterfaces = new ServerSocket(port);
ServerSocket onlyLocalhost = new ServerSocket(port, 100, Inet4Address.getByName("localhost"));) {
Assert.assertEquals(allInterfaces.getLocalPort(), port);
Assert.assertEquals(onlyLocalhost.getLocalPort(), port);
Assert.assertTrue(allInterfaces.isBound());
Assert.assertTrue(onlyLocalhost.isBound());
}
}
}
What I tried:
- Listen on all interfaces explicitly with
Inet4Address.getByName("0.0.0.0")
orInet6Address.getByName("::")
but with or without this specification,lsof
shows listening on all interfaces:*:12340
- I switched the order of binding (first
localhost
and then all interfaces) and with binding from different processes, but OS X still allows the binding. - I searched for a similar problem, but didn't find this problem... Binding to all interfaces of a single network interface multiple interface bind on same port Can I bind multiple servers to the same TCP port? Can socket client and server on the same computer bind to same port?