欢迎亚博app买球官方网站!我们只为解决化工装备的难题!提供化工装备一站式的整体解决方案!

亚博app买球-亚博app英超买球首选

亚博app买球

石化装备制造行业系统方案提供商

专注压力容器生产、研发、制造具有一、二、三类压力容器制造许可证

全国咨询热线 0510-80751588

当前位置: 首页 > 公司动态 > 行业百科

局域网中的UDP广播搜索设备信息

作者:亚博app买球    发布日期:2021-03-30 20:28:39

文章目录

什么是UDP?

这是用户数据报协议,也称为用户数据报协议。它是一个简单的面向数据报的传输层协议。正式规格为RFC 768; UDP为应用程序提供了一种无需建立连接的方式。发送封装的IP数据报的方式

UDP核心API DatagramSocket构造方法简介DatagramSocket常用方法DatagramPacket构造方法DatagramPacket常用方法

通常球探体育比分直播 ,get方法用于获取数据报的发送者信息,而set方法用于设置数据报的接收者信息。当然,如果使用多参数构造方法,则可以减少使用set方法。

单播,广播和多播案例介绍

这种情况分为UDP提供程序(即,正在搜索的设备,例如局域网中的智能设备)和UDP搜索器(例如udp 广播亚博网站有保障的 ,局域网中的手机)。

需要完成的功能是通过手机在局域网中查找智能设备的唯一标识。假设唯一标识符是UUID值的字符串,则搜索后将打印出该唯一标识符。

UDP提供程序需要实现的功能是循环侦听特定端口,然后解析接收到的数据,确定数据是否符合预定格式,从中获取发送者的响应端口,并响应唯一的UUID值UDP搜索器。

UDP搜索者需要实现的功能是监视特定端口并发送LAN​​广播。发送广播时,在数据中设置监听端口。因此,您需要先打开监视功能,然后才能发送广播。一旦收到响应数据,就可以解析设备信息。

从下面开始编码udp 广播,首先是MessageCreator类,该类用于封装和解析端口以及设备的唯一标识

/**
 * 消息创建者
 */
public class MessageCreator {
    private static final String SN_HEADER = "Receive Port I'm UDPProvider (SN):"; //UDPProvider 回复的sn
    private static final String PORT_HEADER = "I'm UDPSearcher,Please send to (Port):"; //UDPSearcher的响应端口
    public static String buildWithPort(int port) {
        return PORT_HEADER + port;
    }
    public static int parsePort(String data){
        if (data.startsWith(PORT_HEADER)) {
            return Integer.parseInt(data.substring(PORT_HEADER.length()));
        }
        return -1;
    }
    public static String buildWithSn(String sn) {
        return SN_HEADER + sn;
    }
    public static String parseSn(String data){
        if (data.startsWith(SN_HEADER)) {
            return data.substring(SN_HEADER.length());
        }
        return null;
    }
}

然后是UDPProvider类

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.UUID;
/**
 * UDP 提供者,用于提供服务
 */
public class UDPProvider {
    public static void main(String[] args) throws IOException {
        //生成一份唯一标识
        String sn = UUID.randomUUID().toString();
        Provider provider = new Provider(sn);
        provider.start();
        //读取任意字符退出
        System.in.read();
        provider.exit();
    }
    private static class Provider extends Thread {
        private final String sn;
        private boolean done = false;
        private DatagramSocket ds = null;
        public Provider(String sn) {
            super();
            this.sn = sn;
        }
        @Override
        public void run() {
            super.run();
            System.out.println("UDPProvider Started");
            try {
                // 作为接收者,指定一个端口用于数据接收
                ds = new DatagramSocket(20000);
                while (!done) {
                    //构建接收实体
                    final byte[] buf = new byte[512];
                    DatagramPacket receivePack = new DatagramPacket(buf, buf.length);
                    //开始接收
                    ds.receive(receivePack);
                    //打印接收到的信息与发送者的信息
                    String ip = receivePack.getAddress().getHostAddress();//发送者的ip
                    int port = receivePack.getPort();//发送者的端口
                    int dataLen = receivePack.getLength();//数据包长度
                    String data = new String(receivePack.getData(), 0, dataLen);//数据内容
                    //打印发送者ip/端口/数据
                    System.out.println("UDPProvider receive from ip:" + ip + "\tport:" + port + "\tdata:" + data);
                    //解析响应端口号
                    int responsePort = MessageCreator.parsePort(data);
                    if (responsePort != -1) {
                        //构建一份回送数据将设备的sn返回给搜索者
                        String responseData = MessageCreator.buildWithSn(sn);
                        byte[] responseDataBytes = responseData.getBytes();
                        //直接根据发送者构建一份回送信息
                        DatagramPacket responsePacket = new DatagramPacket(responseDataBytes,
                                responseDataBytes.length,
                                receivePack.getAddress(),//发送者的ip拿来指定为接收端ip
                                responsePort); //回送到指定端口
                        ds.send(responsePacket);
                    }
                }
            } catch (Exception ignored) {
            } finally {
                close();
            }
            //完成
            System.out.println("UDPProvider Finished");
        }
        private void close() {
            if (null != ds) {
                ds.close();
                ds = null;
            }
        }
        /**
         * 结束
         */
        void exit() {
            done = true;
            close();
        }
    }
}

最后是UDPSearcher类

import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
 * UDP 搜索者
 */
public class UDPSearcher {
    //监听回送端口号
    private static final int LISTENER_PORT = 30000;
    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("UDPSearcher  Started");
        //开启监听30000端口
        Listener listener = listen();
        //发送广播
        sendBroadcast();
        //读取任意信息结束
        System.in.read();
        List<Device> devices = listener.getDevicesAndClose();
        for (Device device : devices) {
            System.out.println("Device:" + device.toString());
        }
        System.out.println("UDPSearcher  Finished");
    }
    /**
     * 监听UDP提供者的回应
     */
    private static Listener listen() throws InterruptedException {
        System.out.println("UDPSearcher  start listen");
        CountDownLatch countDownLatch = new CountDownLatch(1);
        Listener listener = new Listener(LISTENER_PORT, countDownLatch);
        listener.start();
        countDownLatch.await(); //等待监听启动完成,这里是阻塞的
        return listener;//启动完成就返回监听
    }
    /**
     * 发送广播开始搜索UDP提供者
     *
     * @throws IOException
     */
    private static void sendBroadcast() throws IOException {
        System.out.println("UDPSearcher sendBroadcast Started");
        // 作为搜索方,无需指定端口,让系统自动分配
        DatagramSocket ds = new DatagramSocket();
        //发送一份请求数据,暴露监听端口
        String requestData = MessageCreator.buildWithPort(LISTENER_PORT);
        byte[] requestDataBytes = requestData.getBytes();
        //创建一个DatagramPacket
        DatagramPacket requestPacket = new DatagramPacket(requestDataBytes,
                requestDataBytes.length);
        //指定接收方的ip地址,由于用的是本机接收,所以可以用localhost
        //requestPacket.setAddress(InetAddress.getLocalHost());
        //或者指定接收端具体ip也可以,这里用的是受限的广播地址
        //requestPacket.setAddress(InetAddress.getByName("255.255.255.255"));
        //给特定网段广播地址发送
        requestPacket.setAddress(InetAddress.getByName("192.168.1.255"));
        //指定接收方的端口号
        requestPacket.setPort(20000);
        //开始发送广播
        ds.send(requestPacket);
        ds.close();
        //发送广播完成
        System.out.println("UDPSearcher sendBroadcast Finished");
    }
    /**
     * 目标设备(UDP提供者)
     */
    private static class Device {
        final int port;
        final String ip;
        final String sn;
        public Device(int port, String ip, String sn) {
            this.port = port;
            this.ip = ip;
            this.sn = sn;
        }
        @Override
        public String toString() {
            return "Device{" +
                    "port=" + port +
                    ", ip='" + ip + '\'' +
                    ", sn='" + sn + '\'' +
                    '}';
        }
    }
    //监听线程
    private static class Listener extends Thread {
        private final int listenPort;
        private final CountDownLatch countDownLatch;
        private final List<Device> devices = new ArrayList<>();
        private boolean done = false;
        private DatagramSocket ds = null;
        public Listener(int listenPort, CountDownLatch countDownLatch) {
            super();
            this.listenPort = listenPort;
            this.countDownLatch = countDownLatch;
        }
        @Override
        public void run() {
            super.run();
            //通知已启动
            countDownLatch.countDown();
            try {
                //监听回送端口
                ds = new DatagramSocket(listenPort);
                while (!done) {
                    //构建接收实体
                    final byte[] buf = new byte[512];
                    DatagramPacket receivePack = new DatagramPacket(buf, buf.length);
                    //开始接收
                    ds.receive(receivePack);
                    //打印接收到的信息与发送者的信息
                    String ip = receivePack.getAddress().getHostAddress();//发送者的ip
                    int port = receivePack.getPort();//发送者的端口
                    int dataLen = receivePack.getLength();//数据包长度
                    String data = new String(receivePack.getData(), 0, dataLen);//数据内容
                    System.out.println("UDPSearcher receive from ip:" + ip + "\tport:" + port + "\tdata:" + data);
                    //解析sn并添加设备
                    String sn = MessageCreator.parseSn(data);
                    if (null != sn) {
                        Device device = new Device(port, ip, sn);
                        devices.add(device);
                    }
                }
            } catch (Exception e) {
            } finally {
                close();
            }
            System.out.println("UDPSearcher listener finished");
        }
        private void close() {
            if (null != ds) {
                ds.close();
                ds = null;
            }
        }
        List<Device> getDevicesAndClose() {
            done = true;
            close();
            return devices;
        }
    }
}

测试

首先打开UDPProvider监视广播并将设备信息发送给搜索者

然后打开UDPSearcher发送广播并收听您自己的特定端口以获取设备信息

如您所见hg8868体育投注 ,同时发现了2台设备。

TEL:135-8501-5999 FAX:0510-85180729 EMAIL:wxdf888@163.com

亚博app买球-宜兴厂

(宜兴工厂地址:无锡•宜兴市周铁镇兴达路8号)

备案号:苏ICP备17065672号-5

Copyright © 2019-2020 亚博app买球 版权所有