[英]Java: Receiving an UDP datgram packet with multiple DatagramSockets
我正在尝试实现一种将UDP数据包发送到多个接收者的方法。 我认为在接收DatagramSocket实例上设置setReuseAddress(true)
应该可行。
我的问题是,在某些情况下,我需要限制与本地计算机的通信-因此是localhost接口(在下面的演示代码中,useLocalhost = true)。 在这种情况下,突然只有第一个接收器套接字获得了传入的数据包,而另外两个则看不到任何东西。
我在Windows(oracle 64bit)和Linux(OpenJDK 64bit)上进行了测试,因此我只看到三种可能性:
参见下面的一个最小的工作示例来演示这一点。 请注意,我正在使用广播地址来模拟来自真实外部主机的网络数据包。
如果一切顺利,您应该在最后看到三行(按此顺序或不同的顺序):
Thread-0 - packet received
Thread-1 - packet received
Thread-2 - packet received
public static void main(String[] args) throws Exception {
boolean useLocalhost = true;
InetSocketAddress addr;
String sendPacketTo = "192.168.1.255"; // we use broadcast so that packet comes from an real external address
if (useLocalhost)
sendPacketTo = "localhost"; // does not work (only listener 1 received packet)
addr = new InetSocketAddress(15002);
new MyThread(addr).start(); // Datagram socket listener 1
new MyThread(addr).start(); // Datagram socket listener 2
new MyThread(addr).start(); // Datagram socket listener 3
DatagramSocket so = new DatagramSocket();
so.setBroadcast(true); // does not change anything
so.connect(new InetSocketAddress(sendPacketTo, 15002));
so.send(new DatagramPacket("test".getBytes(), 4));
Thread.sleep(1000);
System.exit(0);
}
public static class MyThread extends Thread {
DatagramSocket socket;
public MyThread(InetSocketAddress addr) throws SocketException {
super();
setDaemon(true);
socket = new DatagramSocket(null);
socket.setReuseAddress(true);
socket.setBroadcast(true); // does not change anything
socket.bind(addr);
System.out.println("Listener started: " + socket.getLocalAddress());
}
public void run() {
byte[] buf = new byte[10];
DatagramPacket p = new DatagramPacket(buf, buf.length);
try {
socket.receive(p);
System.out.println(Thread.currentThread().getName() + " - packet received");
} catch (IOException e) {
e.printStackTrace();
}
}
}
192.168.1.255是广播地址,因此根据UDP广播规则广播数据报。 127.0.0.1是单播地址,因此数据包是单播的。 这样您就会获得不同的行为。
正如@DavidSchwartz所评论的那样,您的代码是混合的。 例如,连接到广播地址没有很多意义,绑定也没有任何意义。 我认为您正在寻找的是组播。
您可以在localhost上使用多播,但是,要使其正常工作,需要注意一些事项。
例如:lo0(127.0.0.1)en0(192.168.0.111)en1(10.1.0.111)
示例代码:iMulticastSocketInterfaceIPAddress将是三个接口之一
/* use setsockopt() to request that the kernel join a multicast group */
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr=inet_addr( "239.192.0.133" );
myAddress.sin_addr.s_addr = mreq.imr_multiaddr.s_addr;
mreq.imr_interface.s_addr=( htonl(iMulticastSocketInterfaceIPAddress) );
theErr = setsockopt( CFSocketGetNative( mSocketBroadcast ) ,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.