2

为什么以下代码不抛出“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:\用户\管理员>netstat -a -n | 找到str 10000
  TCP 0.0.0.0:10000 0.0.0.0:0 监听
  TCP 127.0.0.1:10000 0.0.0.0:0 监听
  TCP 127.0.0.2:10000 0.0.0.0:0 监听
  TCP [::]:10000 [::]:0 监听

我在 Windows Server 2008 R2(64 位)上运行它,并且“ipconfig /all”仅显示一个网络适配器/接口(其他网络适配器被禁用)。但是,在其他一些机器上,这个程序实际上确实抛出了预期的“java.net.BindException:地址已经在使用:JVM_Bind”!

会发生什么?

4

1 回答 1

5

您可以在不同的 IP 地址上绑定相同的端口号。操作系统可以通过它们的目标 IP 地址以及它们的 TCP 端口号来区分传入的数据包。

操作系统为127.0.0.1:1000和保留单独的 serverSocket 没有问题127.0.0.2:1000。它知道每个数据包属于哪里——即使它打开了一个新连接。

请注意,IP 地址0.0.0.0就是这样 - IP 地址(它不是一个有效的IP 地址,因为 IP 数据包可以在那里发送,但我不能支持0.0.0.0 == any任何一个)。如果要侦听所有地址,请改为提供null给 InetSocketAddress。此时,您有更大的机会获得所需的异常(除非操作系统决定通配符侦听具有较低的优先级并且不会真正重叠特定的侦听,因此它们可以绑定两者)。

另请注意,设置setReuseAddress不会影响绑定。它只会影响连接被拒绝或接受的一些细节。

作为旁注 - 等待三亿年有什么意义?

于 2013-01-03T06:32:24.200 回答