问题描述
说我启动一个简单的UDP服务器:nc -u localhost 10000
还有一个简单的UDP客户端:nc -ul 10000
那么在Java中,是否有可能接收服务器发送的消息而不会出现“已经使用地址”异常,因为已经有一个客户端了?
编辑:这是我正在使用的代码:
DatagramSocket socket = new DatagramSocket(port);
new Thread(() -> {
try {
while(true) {
byte[] receiveData = new byte[256];
DatagramPacket receivePacket = new DatagramPacket(receiveData,receiveData.length);
socket.receive(receivePacket);
String message = new String( receivePacket.getData(),receivePacket.getLength()).trim();
}
}
catch (SocketException ignore) {}
catch (IOException e) { e.printstacktrace(); }
}).start();
这将导致java.net.BindException:地址已在使用中(绑定失败)。
使用此:
DatagramSocket socket = new DatagramSocket(null);
socket.setoption(SO_REUSEPORT,true);
socket.setoption(SO_REUSEADDR,true);
new Thread(() -> {
try {
while(true) {
byte[] receiveData = new byte[256];
DatagramPacket receivePacket = new DatagramPacket(receiveData,receivePacket.getLength()).trim();
}
}
catch (SocketException ignore) {}
catch (IOException e) { e.printstacktrace(); }
}).start();
不产生任何异常,但我不会收到服务器发送的消息。
编辑2:在实际情况下,服务器正在广播消息。
解决方法
应该可以利用StandardSocketOptions.SO_REUSEPORT
:
对于面向数据报的套接字,套接字选项通常允许将多个UDP套接字绑定到相同的地址和端口。
Linux内核从3.9开始支持此功能。
在Windows上,您可能需要使用SO_REUSEADDR
,但我不确定。
使用SO_REUSEADDR
SO_REUSEADDR套接字选项允许一个套接字强制绑定到另一个套接字正在使用的端口。