Java:接收具有多个DatagramSockets的UDP datgram数据包

标签 java udp datagram

我正在尝试实现一种将 UDP 数据包发送到多个接收方的方法。我认为在接收 DatagramSocket 实例上设置 setReuseAddress(true) 应该是可行的。

我的问题是,在某些情况下,我需要限制与本地计算机的通信 - 因此需要本地主机接口(interface)(下面的演示代码中的 useLocalhost=true)。在这种情况下,突然只有第一个接收器套接字收到传入的数据包,另外两个套接字什么也看不到。

我在 Windows(oracle 64 位)和 Linux(OpenJDK 64 位)上对此进行了测试,因此我只看到三种可能性:

  1. 这是一种预期的已知行为(我不理解整个机制 - 也就是“我大脑中的错误”)
  2. Java JRE 中存在错误
  3. 我的代码中有一个错误。

是否有人对此主题有任何经验,我可以帮助确定问题出在哪里吗?

请参阅下面的最小工作示例来演示这一点。 请注意,我使用广播地址来模拟来自真实外部主机的网络数据包。

如果一切顺利,您应该在末尾看到三行(按此顺序或不同顺序):

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 评论的那样,您的代码是混合体。例如,连接到一个广播地址没有太多意义,绑定(bind)到它也没有什么意义。我认为您正在寻找的是多播。

关于Java:接收具有多个DatagramSockets的UDP datgram数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14940702/

相关文章:

java - 推荐的 Maven 存储库搜索引擎?

java - 使用 JUnit 测试异常。即使异常被捕获,测试也会失败

c - 向所有客户端发送套接字 udp c

java - VoIP RTP 流从/到服务器(在 Java 中)到/从 android

java - 我没有收到来自 Java 的 DatagramPacket 的响应

java - 当用户输入单词 "exit"时,如何使用 Java 中的 Scanner 退出 do-while 循环?

java - Android 加载全图 Recyclerview Cardview

python - 如何在python中停止udp套接字线程?

c# - UDP通信快速填满内存

Java 丢弃了一半的 UDP 数据包