java发送组播或广播包并不复杂网上有很多文章,比如下面的两篇:
《Java实现组播(multicast)简单例子》
《Java 网络编程案例:使用 MulticastSocket 实现多点广播》
这些例子都大同小异,拿来就可以用,我刚开始使用组播/广播时就是这样抄个例子,编译,运行,收到消息—完美

但是,当我们的项目在开始运行时,发现问题来了:有时会收不到某台主机发送的组播包,开始以为是路由器或交换阻止组播包通过,就改为广播.改为广播后,发现问题依然存在.
经过反复测试,发现了规律,当电脑上有多块网卡(虚拟网卡也算)时,就有可能无法发出组播包数据,但自己可以收到自己发送的组播/广播包。
哇哦,原来与多网卡环境有关。有了这个规律,再去百度发现不少关于多网卡环境下发送组播/广播包问题的文章,比如这个
《解决多网卡环境下使用特定网卡广播UDP消息的问题》
这篇文章开头的内容就给出了解决办法,如下图:

看了第一条我就明白了。这是最重要的。
一般情况下,我们向一个IP地址发送数据,我们并不需要指定用哪块网卡发送,因为目标地址明确,底层网卡驱动会帮我们选择合适的网卡发送数据,
但广播或组播就不同,广播或组播地址不是一个指向单一主机的地址,在没有明确的目标指向性的情况下,底层网卡驱动会选择找到第一块网卡做为默认网卡发送数据。如果这时这个默认网卡是一个虚拟网卡(比如我的电脑上装了虚拟机就有一块虚拟网卡),那么发送组播数据就没有真的通过物理网卡发出。而只能被自己接收到。因为这个原因,对于多网卡环境下,发送广播或组播包就必须要指定用哪块网卡发送。

所以我的解决办法就是:遍历所有物理网卡,在每一块网卡上都把组播或广播数据发送一遍,接收组播包时将要明确将每一块物理网卡加入到组播地址中。
下面是我的实现代码片段:

发送组播或广播:

 /*** 向指定的组播或广播地址和端口发送组播数据* @param group 组播或广播地址* @param port 端口* @param message 发送的数据* @param ttl  time-to-live for multicast packets * @param nic 指定发送数据的网卡* @throws IOException*/public static void sendMulticast(InetAddress group,int port,byte[] message, Integer ttl,NetworkInterface nic) throws IOException{checkArgument(null != group,"group is null");// 如果地址不是组播或广播地址则抛出异常checkArgument(group.isMulticastAddress() || isBroadcast(group),"group %s is not a multicast or broadcast address",group);checkArgument(message != null && message.length > 0,"message is null or empty");checkArgument(null != nic,"nic is null");// 获取网卡的绑定的所有IP地址枚举对象Enumeration<InetAddress> nifAddresses = nic.getInetAddresses();if(!nifAddresses.hasMoreElements()){System.out.printf("NOT ADDRESS ON %s\n",nic.toString());return;}// 从网卡上绑定的IP地址创建的InetSocketAddress 对象InetSocketAddress inetAddr= new InetSocketAddress(nifAddresses.nextElement(),0);DatagramSocket ds = null;try {if(group.isMulticastAddress()){// MulticastSocket 绑定到指定的网卡@SuppressWarnings("resource")MulticastSocket ms =  new MulticastSocket(inetAddr);if(ttl != null){ms.setTimeToLive(ttl);}ds = ms;}else{// DatagramSocket绑定到指定的网卡ds = new DatagramSocket(inetAddr);ds.setBroadcast(true);}ds.send(new DatagramPacket(message, message.length,group,port));} finally {if(ds != null){ds.close();}}}/*** 向指定的组播或广播地址和端口发送组播数据* @param group 组播或广播地址* @param port 端口* @param message 发送的数据* @param ttl  time-to-live for multicast packets * @throws IOException*/public static void sendMulticast(InetAddress group,int port,byte[] message, Integer ttl) throws IOException{checkArgument(null != group,"group is null");// 如果地址不是组播或广播地址则抛出异常checkArgument(group.isMulticastAddress() || isBroadcast(group),"group %s is not a multicast or broadcast address",group);checkArgument(message != null && message.length > 0,"message is null or empty");// 遍历所有物理网卡,将数据在每个网卡上发送一次for(NetworkInterface nic:getNICs(Filter.UP,Filter.PHYICAL_ONLY)){sendMulticast(group,port,message,ttl,nic);}}/*** 判断一个地址是否为广播地址(255.255.255.255)* @param addr* @return*/public static boolean isBroadcast(InetAddress addr){return addr.getHostAddress().equals("255.255.255.255");}

接收广播或组播包代码片段

 /*** socket初始化* @return 当前对象* @throws IOException 创建组播对象({@link MulticastSocket})时出错*/public MultiCastDispatcher init() throws IOException{if(null == datagramSocket){if(NetworkUtil.isBroadcast(group)){datagramSocket = new DatagramSocket(port);datagramSocket.setBroadcast(true);}else{MulticastSocket multicastSocket = new MulticastSocket(port);// 遍历所有物理网卡,对每块网卡执行joinGroupfor(NetworkInterface nic:NetworkUtil.getNICs(Filter.UP,Filter.PHYICAL_ONLY)){InetSocketAddress inetAddr= new InetSocketAddress(group,0);multicastSocket.joinGroup(inetAddr,nic);}this.datagramSocket = multicastSocket;}}return this;}/*** 循环接收group,port指定的组播地址发送的数据并交给{@link #processor}处理*/@Overridepublic void run() {stopListener = Boolean.FALSE;DatagramPacket packet = new DatagramPacket(message, message.length);try {while(!Boolean.TRUE .equals(stopListener)){try {checkArgument(datagramSocket != null,"multicastSocket is uninitizlied");datagramSocket.receive(packet);byte[] recevied = new byte[packet.getLength()];System.arraycopy(message, 0, recevied, 0, packet.getLength());// 处理收到的广播/组播数据if(!processor.apply(recevied)){break;}} catch (Exception e) {if(!onerr.apply(e)){break;}}}} finally {try {if(datagramSocket instanceof MulticastSocket){// 遍历所有物理网卡,对每块网卡执行leaveGroupfor(NetworkInterface nic:NetworkUtil.getNICs(Filter.UP,Filter.PHYICAL_ONLY)){InetSocketAddress inetAddr= new InetSocketAddress(group,0);((MulticastSocket) datagramSocket).leaveGroup(inetAddr,nic);}}} catch (IOException e) {e.printStackTrace();}datagramSocket.close();datagramSocket = null;stopListener = null;}             }

上面代码都只是示例片段,完整代码参见我的码云GIT仓库:
发送组播/广播的完整实现方法 net.gdface.utils.NetworkUtil.sendMulticast(InetAddress group, int port, byte[] message, Integer ttl)
https://gitee.com/l0km/common-java/blob/master/common-base2/src/main/java/net/gdface/utils/NetworkUtil.java
接收组播/广播的完整实现类 MultiCastDispatcher
https://gitee.com/l0km/common-java/blob/master/common-base2/src/main/java/net/gdface/utils/MultiCastDispatcher.java

java (多网卡环境下)发送组播广播(multicast/broadcast)失败问题相关推荐

  1. 多网卡环境下(数据网卡+有线网卡)下广播失败问题

    开发环境 python(编程语言) linux(运行系统) 多网卡(数据网卡+有线网卡) 广播失败原因分析 (摘自:java 向网卡发送广播_java (多网卡环境下)发送组播广播(multicast ...

  2. Java网络编程(八)—— 组播和MulticastSocket

    Java网络编程(八)-- 组播和MulticastSocket 文章目录 Java网络编程(八)-- 组播和MulticastSocket 什么是组播 MulticastSocket类 总述 构造方 ...

  3. 网络基本概念之TCP, UDP, 单播(Unicast), 组播(Multicast)

    这篇文章相当低级,但相当重要! 我们周围一切几乎都依赖于把事情抽象成低等级,并在某一点把它具体化,在一些设计概念中,接口层十分清晰并且目标很集中,应用程序不用考虑操作系统如何工作,操作系统也不用考虑硬 ...

  4. 十五、组播(Multicast)

    组播(Multicast) 组播基础 前言 当网络中部署点到多点通信应用时,若采用单播方式,网络中传输的信息量与需要该信息的用户量成正比.多份内容相同的信息发送给不同用户,对信源及网络带宽都将造成巨大 ...

  5. TX2 Linux配置组播(Multicast)

    单播组播广播区别 单播(unicast): 是指封包在计算机网络的传输中,目的地址为单一目标的一种传输方式.它是现今网络应用最为广泛,通常所使用的网络协议或服务大多采用单播传输,例如一切基于TCP的协 ...

  6. Linux 网络协议栈开发基础篇(十)—— 组播(Multicast)基础

    一.组播(Multicast)传输 在发送者和每一接收者之间实现点对多点网络连接. 如果一台发送者同时给多个的接收者传输相同的数据,也只需复制一份的相同数据包.它提高了数据传送效率.减少了骨干网络出现 ...

  7. linux如何运行java程序,Linux环境下运行简单java程序

    一.安装java 1.下载jdk8 选择对应jdk版本下载.(Tips:可在Windows下载完成后,通过FTP或者SSH到发送到Linux上) 2. 登录Linux,切换到root用户 su roo ...

  8. python socket发送组播数据_python3通过udp实现组播数据的发送和接收操作

    本文主要通过对海康摄像头进行抓包,模拟发送了udp包,并抓取摄像头返回的数据包,解析并提取相关信息. 通过抓包发现,海康摄像头发送.接收数据使用udp协议,后来比较发现,使用python模拟起来比较简 ...

  9. android 不能接收组播数据,但能够发送组播数据

    http://blog.csdn.net/hknock/article/details/44244031 Android的Wifi,默认情况下是不接受组播的,见:http://developer.an ...

最新文章

  1. Android实现炫酷的星空变幻效果
  2. PAT甲级1068 Find More Coins (30 分):[C++题解]DP、背包问题、dp输出方案
  3. POJ - 3565 Ants(二分图最小权匹配+KM+思维)
  4. http协议工作流程
  5. java原理—反射机制
  6. Docker操作补充
  7. 自己手写代码实现下拉刷新(对于小项目第三方库太占资源)
  8. 项目需求:基于微信平台的拼团活动系统
  9. Bash脚本15分钟进阶教程-转
  10. python如何调用hslcommunication_C#读写PLC数据问题
  11. 怎么压缩ppt文件大小?
  12. 新浪微博登陆uchome
  13. 卸载office2007不干净问题
  14. pyqt5 选择打开文件夹与读取文件夹图片列表
  15. 为什么C语言长盛不衰,永不会过时?
  16. Tomcat无法启动,报错java.lang.NoClassDefFoundError: or...
  17. Linux下samba的安装与配置
  18. 硬件物料清单bom检查小技巧
  19. 从0到N建立高性价比的大数据平台
  20. Radiology:人工智能系统脑MRI鉴别诊断精度接近神经放射科医生水平

热门文章

  1. python数据解析——xpath爬取文字和图片
  2. java买票程序_Java如何编写自动售票机程序
  3. 【大数据课程设计】城市公交网络分析与可视化(以青岛市为例)
  4. 2022美国大学生数学建模竞赛F题思路
  5. contiki学习笔记(十)隐式网络时间同步、protothreads
  6. Linux驱动:在imx6ull上适配RT3070 USB WiFi网卡
  7. (教程)中兴机顶盒免拆机变身游戏机
  8. 关于MSMQ(System.Messaging.MessageQueue)安装及在.NET Framework框架下的简单应用实现,以解决大并发请求问题
  9. 微信小程序云开发使用创建
  10. java 中的静态变量,静态代码块,动态代码块,构造方法执行顺序的深入探究