我有一个使用UDP连接的应用程序,现在当我尝试不止一次运行应用程序时,它给我一个例外
java.net.BindException: Address already in use: Cannot bind
但在我的另一个使用tcp连接的应用程序中,我可以打开同一个应用程序的两个实例,并且其工作正常.为什么这个错误只与UDP连接?
编辑:
TCP socket: Socket clientSocket= new Socket(ipAddress, 8000); Socket clientSocket1= new Socket(ipAddress, 8000);
如果我像上面一样创建TCP套接字,使用相同的端口,它不会抛出任何错误.但是,如果我用UDP Socket做到这一点,它会给我一个例外,为什么?
它与TCP和UDP之间的区别有关.当您创建TCP套接字时,您正在创建与另一台计算机上的端口的同步客户端连接,并且当您连接到地址时,您实际上也会在套接字上获得本地端口.因此,在您的示例代码中,创建的两个套接字可能是
clientSocket = localhost:2649 <-> ipAddress:8000 clientSocket1 = localhost:2650 <-> ipAddress:8000
请注意,虽然它们的远程地址相同,但本地地址具有不同的端口,这就是允许这样做的原因.因此,本地远程计算机可以使用已建立的端口可靠地来回发送数据.
对于UDP,情况并非如此(我假设您正在使用DatagramSocket).由于UDP是异步的(与TCP之类的同步相反),为了接收数据,您不会创建与另一台特定机器的绑定,因此例如,如果您尝试
DatagramSocket udp1 = new DatagramSocket(8000); // = localhost:8000 <-> ? DatagramSocket udp2 = new DatagramSocket(8000); // = localhost:8000 <-> ?
udp套接字不知道数据来自何处,因此不能有像TCP这样的唯一映射,与TCP不同,您指定的端口是您的机器端口,而不是远程机器端口.
创建UDP套接字时想到它的另一种方法就像创建TCP服务器套接字一样.当您创建TCP服务器套接字时,它正在等待来自某台计算机的连接但该计算机未知,并且当您创建TCP服务器套接字时,您指定的端口是本地端口:
ServerSocket ss1 = new ServerSocket(8000); // = localhost:8000 <-> ? ServerSocket ss2 = new ServerSocket(8000); // = localhost:8000 <-> ?
与UDP类似,这将创建绑定异常,因为该端口用于本地计算机,并且映射不再是唯一的.但是,当您接受服务器套接字上的连接时,远程计算机会发挥作用以使套接字唯一,就像创建Socket到远程计算机时一样:
Socket s1 = ss1.accept();// localhost:8000 <-> remoteIp1:12345 Socket s2 = ss1.accept();// localhost:8000 <-> remoteIp2:54321
请注意,虽然本地地址相同,但套接字的远程地址不同,因此总映射(localip:port < - > remoteip:port)现在是唯一的.
因此,在某种程度上,您可以将UDP套接字视为类似于TCP服务器套接字,这就是您必须将其绑定到唯一端口的原因.