java多播(组播)多网卡监听实现

知识点:单播:与某个人聊天      多播:拉了个群进行群聊  (多播IP地址就是D类IP地址,即224.0.0.0至239.255.255.255之间的IP地址)  广播:类似微信群发     可以这么简单理解,具体大家另行了解。

问题描述:在笔记本电脑上跑多播服务,偶现收不到客户端发送的多播信息,关闭其中一个不用网卡重启服务就可以收到了

问题分析:通过抓包,发现客户端发送的多播消息已经到了笔记本电脑上,只是多播服务没有收到。证明网络是通的,并且多播客户端已经成功发送消息。

故怀疑是多网卡问题,因为笔记本电脑当时有线网卡和无线网卡同时在运行,而多播服务默认监听其中一个网卡A,当多播客户端通过另一个网卡B发送消息时,

则多播服务无法收到消息。

  MulticastSocket ds=null;
        DatagramPacket packet = null;
        // 存储发来的消息
        byte[] buf = new byte[1024];
        try {
            //使用多播
            ds = new MulticastSocket(10007);
            InetAddress   receiveAddress=InetAddress.getByName("239.106.106.255");
            ds.joinGroup(receiveAddress);
            packet = new DatagramPacket(buf, buf.length);
            while (true) {
                ds.receive(packet);
                buf = Arrays.copyOfRange(packet.getData(), 0, packet.getLength());
                //消息处理
               // parse(packet.getAddress(), buf);
            }
        } catch (Exception e) {
           logger.error("寻址监听出错",e);
        } finally {
            ds.close();
查看 InetAddress.getByName("239.106.106.255")的源码 如下图:

可以确定原来的代码确实只监听了默认的网卡地址。

解决方案:1、多播服务监听所在服务器(电脑)的所有有效网卡地址。

                  2、多播客户端发送其所有有效网卡地址。

我是做服务端的,毫无疑问选择的是方案一。

实现过程

  public void start() throws Exception {

        MulticastSocket ds = null;
        DatagramPacket packet = null;
        // 存储发来的消息
        byte[] buf = new byte[1024];
        try {
            //使用多播
            ds = new MulticastSocket(10007);
            InetAddress  receiveAddress=InetAddress.getByName("239.106.106.255");
            //获取有效网卡地址
            List<NetworkInterface> addressList = NetworkUtil.getNetworkInterfaces();
            //端口不冲突就行
            int port = 10009;
            for (NetworkInterface networkInterface : addressList) {
                InetSocketAddress inetSocketAddress = new 
                InetSocketAddress(receiveAddress, port);
                //将有效网卡加入组播
                ds.joinGroup(inetSocketAddress, networkInterface);
                port++;

            }
            packet = new DatagramPacket(buf, buf.length);
            while (true) {
                ds.receive(packet);
                buf = Arrays.copyOfRange(packet.getData(), 0, packet.getLength());
     
            }
        } catch (Exception e) {
            logger.error("寻址监听出错", e);
        } finally {
            if(ds!=null){
                 ds.close();
             } 
        }
    }
public class NetworkUtil {
    private final static String LOCAL_IP = "127.0.0.1";
    /**
     * 获取本机有效所有网卡地址
     *
     * @return  List<NetworkInterface> ip列表
     * @throws
     */
    public static List<NetworkInterface> getNetworkInterfaces() throws Exception {
        List<NetworkInterface> localIPlist = new ArrayList<NetworkInterface>();
        Enumeration<NetworkInterface> interfs = 
        NetworkInterface.getNetworkInterfaces();
        if (interfs == null) {
            return null;
        }
        while (interfs.hasMoreElements()) {
            NetworkInterface interf = interfs.nextElement();
            Enumeration<InetAddress> addres = interf.getInetAddresses();
            while (addres.hasMoreElements()) {
                InetAddress in = addres.nextElement();
                if (in instanceof Inet4Address) {
                    if (!LOCAL_IP.equals(in.getHostAddress())){
                        localIPlist.add(interf);
                    }
                }
            }
        }
        return localIPlist;
    }

}

问题验证:验证网卡是否加入多播组

        windows:   执行   netsh interface ipv4 show joins

        Linux:  执行 netstat  -g

我的是windows,如图:可以看出有线网卡和无线网卡都加入了多播组。至此问题解决

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值