Linux上的Java:侦听绑定本地地址上的广播消息【JAVA教程】

!
也想出现在这里? 联系我们
信息

Linux上的Java:侦听绑定本地地址上的广播消息,第1张

概述Linux上的Java:侦听绑定本地地址上的广播消息

我有一个奇怪的要求,能够在linux机器上侦听来自Java的多个networking接口,并确定它们中的一个是否接收到某种types的UDP数据包。 我需要的输出数据是有问题的接口的IP地址。 有没有办法在Java中做到这一点?

听通配符地址(新的DatagramSocket(端口))没有帮助,因为虽然我得到广播数据包,我不能确定他们通过接口的本地IP地址。 绑定到某个接口(新的DatagramSocket(端口,地址))时监听广播根本不接收数据包。 这个案例值得一个代码示例,显示了我想要做的事情:

Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface ni = (NetworkInterface) interfaces.nextElement(); Enumeration addresses = ni.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress address = (InetAddress)addresses.nextElement(); if (address.isLoopbackAddress() || address instanceof Inet6Address) continue; //Not interested in loopback or ipv6 this time,thanks DatagramSocket socket = new DatagramSocket(PORT,address); //Try to read the broadcast messages from socket here } }

我也尝试着使用根据接口的真实IP开始构build的广播地址初始化套接字,其余的根据正确的networking掩码:

byte [] mask = { (byte)255,0 }; byte[] addrBytes = InetAddress.getByname(\”126.5.6.7\”).getAddress(); for (int i=0; i < 4; i++) { addrBytes[i] |= ((byte)0xFF) ^ mask[i]; } InetAddress bcastAddr = InetAddress.getByAddress(addrBytes);

这只是在构造DatagramSocket时抛出一个BindException。

如何在.NET中侦听windows广播消息?

所有接口上的UDP广播

如何在windows Vista中模拟/replace/重新启用古典混音器控件(或命令)?

linux上的快速用户空间进程间通知方法?

在Win32 SDK中使用PlaySound时,如何检测声音何时播放完毕?

编辑: BindException(java.net.BindException:无法分配请求的地址)调用DatagramSocket的广播地址(例如126.255.255.255)的构造函数只有最新的Ubuntu 9.04(可能不是Ubuntu,但内核版本特定的问题,但) 。 使用Ubuntu 8.10,这个工作,以及我正在处理的红帽发行版(RHEL 4.x)。

显然,绑定到某个本地IP时不接收数据包是正确的行为 ,尽pipe在windows中是有效的。 我需要在linux(RHEL和Ubuntu)上运行。 使用低级别的C代码有一个解决schemesetsockopt(SO_BINDTODEVICE),我无法在Java-API中find。 这并不完全让我爆发乐观,尽pipe:-)

如何用Delphi来播放单音或自定义波形?

如何允许windows 7接受来自地址为“127.0.0.2”的外部设备的UDP消息?

多播系统上的UDP广播

UDP广播接收问题与Ubuntu 9.04,但不是8.04

仅从特定适配器(例如192.168.101.1)发送UDP广播(255.255.255.255); 在windows上

最后,这是一个IPV6 linux内核问题。 通常我已经禁用IPV6,因为它会引起各种头痛。 然而,在Ubuntu 9.04中,禁用IPV6是非常困难的,我放弃了这一点,这让我有些失望。

要收听来自特定界面的广播消息,我将首先创建接口IP地址的“广播版本”:

byte [] mask = { (byte)255,0 }; byte[] addrBytes = InetAddress.getByname(\”126.5.6.7\”).getAddress(); for (int i=0; i < 4; i++) { addrBytes[i] |= ((byte)0xFF) ^ mask[i]; } InetAddress bcastAddr = InetAddress.getByAddress(addrBytes);

当然,如果许多接口都有一个以相同的网络部分开始的IP,那么这并不能真正将我与某个接口绑定,但是对于我来说,这个解决方案已经足够了。

然后我创建该地址(和所需的端口)datagramsocket,它的工作原理。 但不是没有将下列系统属性传递给JVM:

-Djava.net.preferIPv6Addresses=false -Djava.net.preferIPv4Stack=true

我不知道如何IPV6设法中断收听广播,但它确实,并上述参数修复它。

为了重申你的问题,你需要确定接收广播UDP数据包的接口。

如果绑定到通配符地址,则会收到广播,但无法确定接收数据包的网络地址。

如果绑定到特定的接口,则知道您正在接收哪个接口地址,但不再接收广播(至少在linux TCP / IP堆栈上)。

正如其他人所提到的,有一些Java的第三方原始套接字库,例如RockSaw或Jpcap ,它们可以帮助您确定实际接口的地址。

不知道这是否有帮助,但我知道要获得所有网络接口的列表:

Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces();

也许你可以独立绑定到每一个?

刚刚发现了getNetworkInterfaces()的一些很好的例子。

http://www.javadocexamples.com/java/net/NetworkInterface/getNetworkInterfaces().HTML

据我所知,要做到这一点的唯一方法就是用这个方法

IP_RECVDSTADDR

套接字选项。 这个选项应该确保数据包的接口的dst地址在绑定到通配符地址时可用。 所以它应该与广播我也假设。

下面是我从互联网上找到的一个C例子:

如何获取传入数据包的UDP目标地址

我会阅读recvmsg ,然后尝试找出这个接口是否可用Java。

编辑:

我刚刚意识到,如果在Java中支持,可能还有一个选项。 您可能仍然需要IP_RECVDSTADDR套接字选项(不确定),但是可以使用原始套接字并从IP头获取目标地址,而不是使用recvmsg。

使用SOCK_RAW打开您的套接字,您将在每条消息的开始处获得完整的IP标头,包括源地址和目标地址。

下面是一个在linux上用C语言对原始套接字使用UDP的例子:

高级TCP / IP – 原始套接字程序示例

如果这种方法在Java中不起作用,我也会感到惊讶。

EDIT2

还有一个想法。 是否有一个原因,你不能使用多播或您选择了多播广播的特定原因? 据我所知Multicast,你总是知道接收数据包的接口,因为当你加入一个多播组时(特别是通过IP4,通过它的一个IP地址绑定到接口),你总是绑定到特定的接口。

不能发表评论,所以添加这个作为一个答案,而不是。

那很有意思。 虽然很好奇你为什么这样做

byte[] addrBytes = InetAddress.getByname(\”126.5.6.7\”).getAddress();

而不仅仅是

byte[] addrBytes = {126,5,6,7);

或者是接口地址以字符串的形式得到你?

总结

以上是内存溢出为你收集整理的Linux上的Java:侦听绑定本地地址上的广播消息全部内容,希望文章能够帮你解决Linux上的Java:侦听绑定本地地址上的广播消息所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

© 版权声明
THE END
喜欢就支持一下吧
点赞94 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容