在Java中广播UDP数据包的正确且有效的方法是什么?

发布于 2024-12-17 22:14:27 字数 2176 浏览 5 评论 0原文

我需要在每个网络接口上广播 UDP 数据包。起初,我尝试广播到255.255.255.255,但没有结果,后来我发现这个“已经被弃用了大约20年”。因此,我尝试迭代每个网络接口,以获得该接口的广播地址,然后向该地址发送 UDP 数据包。

尽管如此,下面的代码:

public static Collection<InetAddress> getBroadcastAddresses() {
    try {
        Collection<InetAddress> result = new LinkedList<InetAddress>();
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netint : Collections.list(nets))
                for (InterfaceAddress address : netint.getInterfaceAddresses()) {
                    InetAddress broadcastAddress = address.getBroadcast();
                    if (broadcastAddress != null)
                        result.add(broadcastAddress);
                }
        return result;
    } catch (SocketException e) {
        throw new RuntimeException(e);
    }
}

public static void broadcast(int port, DatagramPacket packet,
        DatagramSocket socket, PrintWriter logger) throws IOException {

    packet.setPort(port);

    for (InetAddress address : getBroadcastAddresses()) {
        logger.println("Broadcasting to: "+address);
        packet.setAddress(address);
        socket.send(packet);
    }
    
}

打印了这些东西:

Broadcasting to: /0.255.255.255
Broadcasting to: /255.255.255.255
Broadcasting to: /255.255.255.255
Broadcasting to: /255.255.255.255
Broadcasting to: /255.255.255.255

这真的很烦人。我是否应该获取每个网络接口的 IP 地址和网络掩码并执行按位运算来“构建”正确的广播地址? 在我看来,这就像用 C 语言进行 Unix 套接字编程...是否有一个干净的、 Java 的方式来巧妙地将一个糟糕的 UDP 数据包传递给我网络中的所有好友?

编辑:在网上搜索,结果发现这次我的代码没有损坏。相反,JVM 是。从 InterfaceAddress.getBroadcast() 获取的数据不一致,至少在 Windows 7 下是这样。请参阅示例 这个这个:解决方案似乎设置了一个Java 系统属性,以便使其更喜欢 IPv4 而不是 IPv6,但这对我不起作用。即使使用建议的解决方法,我在每次不同的运行中都会得到不同的结果,并且由于我获得的广播地址显然是随机的,因此我怀疑我获得的数据是从未定义的状态内存位置获取的。

I need to broadcast an UDP packet on every network interface. At first, I tried broadcasting to 255.255.255.255, with no results, and I later discovered that this "has been deprecated for about 20 years". So I tried iterating on every network interface in order to get the broadcast address of the interface and then send an UDP packet to that address.

Still, the following code:

public static Collection<InetAddress> getBroadcastAddresses() {
    try {
        Collection<InetAddress> result = new LinkedList<InetAddress>();
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netint : Collections.list(nets))
                for (InterfaceAddress address : netint.getInterfaceAddresses()) {
                    InetAddress broadcastAddress = address.getBroadcast();
                    if (broadcastAddress != null)
                        result.add(broadcastAddress);
                }
        return result;
    } catch (SocketException e) {
        throw new RuntimeException(e);
    }
}

public static void broadcast(int port, DatagramPacket packet,
        DatagramSocket socket, PrintWriter logger) throws IOException {

    packet.setPort(port);

    for (InetAddress address : getBroadcastAddresses()) {
        logger.println("Broadcasting to: "+address);
        packet.setAddress(address);
        socket.send(packet);
    }
    
}

prints this stuff:

Broadcasting to: /0.255.255.255
Broadcasting to: /255.255.255.255
Broadcasting to: /255.255.255.255
Broadcasting to: /255.255.255.255
Broadcasting to: /255.255.255.255

which is really annoying. Am I supposed to grab the IP address and netmask for every network interface and perform bitwise operations to "build" the correct broadcast address? This seems to me like Unix socket programming in C... Is there a clean, Java way to neatly deliver a miserable UDP packet to all the buddies that crowd my network?

EDIT: searching the web, it turned out that this time my code is not broken. Instead, the JVM is. The data you get from InterfaceAddress.getBroadcast() is inconsistent, at least under Windows 7. See for example this and this: the solution seems to set a Java system property in order to make it prefer IPv4 over IPv6, but this doesn't work for me. Even with the suggested workaround, I get different results on every different run, and since the broadcast address I get is apparently random, I suspect I'm given data taken from undefined state memory locations.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

Saygoodbye 2024-12-24 22:14:27

您需要获取网络IP并标记并将其用于广播。这是简单的部分。然后,您需要收集所有回复,并知道某些服务器可能没有收到 UDP 数据包,并且某些回复可能已丢失。您必须考虑到 UDP 被设计为不可靠的事实。

我会直接解析 ipconfig /all 来获取 IP 和子掩码。即使 ipconfig 也只有 IPv4 的子掩码

You need to get the network IP and mark and use this for broadcast. That the simple part. Then you need to collect all the replies knowing that some servers may not have received the UDP packets and some of the replies could have been lost. You have to allow for the fact that UDP is designed to be unreliable.

I would parse ipconfig /all directly to get the IP and submask. Even ipconfig only has a submask for IPv4

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文