为什么下面的代码没有抛出“java.net.BindException:地址已在使用中:JVM_Bind” 异常?
import java.net.InetSocketAddress;
import java.net.ServerSocket;
public class Test
{
public static void main(String[] args) throws Exception
{
try (ServerSocket socket1 = new ServerSocket();
ServerSocket socket2 = new ServerSocket();
ServerSocket socket3 = new ServerSocket())
{
int port = 10000;
socket1.setReuseAddress(false);
socket1.bind(new InetSocketAddress("0.0.0.0", port));
socket2.setReuseAddress(false);
socket2.bind(new InetSocketAddress("127.0.0.1", port));
socket3.setReuseAddress(false);
socket3.bind(new InetSocketAddress("127.0.0.2", port));
Thread.sleep(Long.MAX_VALUE);
}
}
}
之后运行'netstat'会显示:
C:\Users\Administrator>netstat -a -n | findstr 10000 TCP 0.0.0.0:10000 0.0.0.0:0 LISTENING TCP 127.0.0.1:10000 0.0.0.0:0 LISTENING TCP 127.0.0.2:10000 0.0.0.0:0 LISTENING TCP [::]:10000 [::]:0 LISTENING
我在Windows Server 2008 R2(64位)上运行此命令,而'ipconfig / all'仅显示一个网络适配器/接口(其他网络适配器已禁用)。但是,在其他一些机器上,这个程序确实抛出了预期的“java.net.BindException:Address in in use:JVM_Bind”!
可能会发生什么?
答案 0 :(得分:5)
您可以绑定不同IP地址上的相同端口号。操作系统可以通过目标IP地址和TCP端口号来区分传入的数据包。
操作系统为127.0.0.1:1000
和127.0.0.2:1000
保留单独的serverSocket没有问题。它知道每个数据包所属的位置 - 即使它打开了新连接。
请注意,IP地址0.0.0.0
只是 - 一个IP地址(它不是有效的 IP地址,因为IP数据包可以在那里发送,但我不能任何对0.0.0.0 == any
的支持。如果要监听所有地址,请将null
提供给InetSocketAddress。此时,您有更大的机会获得所需的异常(除非操作系统决定通配符侦听具有较低的优先级并且不会真正重叠特定的侦听,因此它们可以绑定两者)。
另请注意,设置setReuseAddress
不会影响绑定。它只会影响拒绝或接受哪些连接的某些细节。
作为旁注 - 等待三亿年的重点是什么?