2013-01-03 129 views
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:\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:地址已经在使用:JVM_Bind”!

可能会发生什么?

+0

他们是不一样的端口。它们是相同的端口号。不同的套接字可能会根据哪个(虚拟)接口发送相同的数据包而得到通知。 –

+0

但我在该机器上只有一个网络接口 – ManRow

+7

环回虚拟接口有很多IP地址。即使使用相同的端口号,您也可以分别监听它们中的每一个。 –

回答

5

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

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

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

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

作为一个便笺 - 等待三亿年有什么意义?

+0

指定0.0.0.0和null没有区别。这两个意思是INADDR_ANY。出于这个原因,我对之后更具体的绑定工作感到惊讶。如果不存在0.0.0.0,我会期望其他人能够工作,但是没有0.0.0.0已经被绑定。 – EJP

+0

@EJP我原本以为是一样的,但我无法在文档中找到对该想法的支持。我确实发现了0号码在同一个地方也意味着_any_的声明。 –

相关问题