UDP广播在通讯双方互相不知道对方IP的情况下很有用。这种情形我们可以遍历网段实现,但是比较粗暴,如果网段比较大,不是最多256台主机的C类网段的话,很难做遍历

        UDP广播解决这种问题标准方案

        注意,广播和多播是不同的,广播是同时发送给所有主机,而多播是一个特殊的组,必须明确加入退出

目录

一、什么是UDP广播

二、获取手机IP

三、UDP广播

3.1 发送

3.2 接收

四、作为知识基础的IP地址知识


一、什么是UDP广播

        UDP广播分两种:目标地址为255.255.255.255的物理广播,发送给物理网络的所有设备,只要物理联通就能收到,不限网段,但是不能穿过路由器(很显然,如果穿过路由器就会传播给全网络了);目标地址为XXX.XXX.XXX.255(C类)的网段广播,发送给同网段的所有设备,能穿过路由器,同一物理网络的其它网段主机接收不到。

        我用手机热点设备通讯,实测结果如下

            //物理网络广播,对方网段广播,对方收不到但能发送这里
            //双方都物理网络广播,仍然是对方收不到但能发送这里
            //网段广播,对方物理网络广播,能收能发
            //双方都网段广播,能收能发

        上面的“这里”是手机开启热点,“对方”是连接热点的PC。从结果看物理网络广播是不可靠的,还是用网段广播比较好。

二、获取手机IP

        从上面分析我们知道,最好使用网段广播,那么就必须先知道目标网段。目标网段可以根据自身的IP地址推算,热点一般都是C类地址,最后一个字节改为255即可

        代码如下

    public String getLocalIPAddress() {
        Enumeration<NetworkInterface> enumeration = null;
        try {
            enumeration = NetworkInterface.getNetworkInterfaces();
        } catch (Exception e) {
            error_msg.append(e.toString());
        }
        if (enumeration != null) {
            StringBuilder sb = new StringBuilder();
            // 遍历所用的网络接口
            while (enumeration.hasMoreElements()) {
                NetworkInterface nif = enumeration.nextElement();// 得到每一个网络接口绑定的地址
                Enumeration<InetAddress> inetAddresses = nif.getInetAddresses();
                // 遍历每一个接口绑定的所有ip
                if (inetAddresses != null)
                    while (inetAddresses.hasMoreElements()) {
                        InetAddress ip = inetAddresses.nextElement();
                        if (!ip.isLoopbackAddress() &amp;&amp; isIPv4Address(ip.getHostAddress())) {
                            sb.append(ip.getHostAddress());
                        }
                    }
            }
            return sb.toString();
        }
        return "";
    }

    /**
     * Ipv4 address check.
     */
    private static final Pattern IPV4_PATTERN = Pattern.compile("^(" +
            "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}" +
            "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");

    /**
     * Check if valid IPV4 address.
     *
     * @param input the address string to check for validity.
     * @return True if the input parameter is a valid IPv4 address.
     */
    public static boolean isIPv4Address(String input) {
        return IPV4_PATTERN.matcher(input).matches();
    }

         这段代码网上搜来的,我稍微改了一下,直接返回个字符串,不过拼接时候没有分隔符,正式使用最好是返回一个列表

        手机可能返回两个IP地址,一个移动网络的地址,一个是热点的地址,移动网络的地址通常是10网段,热点地址通常是192.168网段,但是——所谓的热点固定是“192.168.43.*”网段的说法已经过时了

        将192开头的地址的最后一段改成255就是热点的网段地址,对这个网段广播即可

三、UDP广播

3.1 发送

        注意,网络发送接收因为可能阻塞,不能在UI线程运行,必须创建线程

            String all_ip = getLocalIPAddress();
            InetAddress ip = InetAddress.getByName("192.168.???.255");
            Log(ip.toString());

            {
                Log("发送数据 ");
                DatagramSocket sender = new DatagramSocket();
                DatagramPacket dpSend = new DatagramPacket(all_ip.getBytes(), all_ip.getBytes().length, ip, 6000);
                sender.send(dpSend);
                Log("数据发送成功");
                sender.close();
            }

        设置IP要根据前面获取到的实际IP网段(代码中的问号处),我的手机是179,不是传说的43。第一行就是根据前面获取IP的方法获得IP列表,不过我只是测试,所以没有进行拆解。

        发送UDP无所谓自身的IP端口,只需要目标IP和端口即可

3.2 接收

        接收数据需要指定接收端口号,同时提供接收缓冲区

                Log("接收数据");
                DatagramSocket receiver = new DatagramSocket(6000);
                byte[] buffer = new byte[10];
                DatagramPacket dpReceive = new DatagramPacket(buffer, buffer.length);
                receiver.receive(dpReceive);
                String datamsg = new String(buffer);
                Log("收到数据" + datamsg);
                Log("关闭接收");
                receiver.close();

        这里只接收了一次,只提供了很小的缓冲区,实际使用要使用循环多次接收并提供足够大的缓冲区

        在连接热点的PC上使用的是UDP测试软件,使用同样的地址和端口,与手机互相发送接收成功。

四、作为知识基础的IP地址知识

        发现很多人对TCP/IP网络和IP地址的相关知识不是很扎实,配网络的时候知道子网掩码网关什么意思,下面列出几个要点

这里结束

原文地址:https://blog.csdn.net/2301_77171572/article/details/134659189

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_32566.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注