【Socket网络编程进阶与实战】------- Socket UDP快速入门

前言

Socket UDP快速入门,demo实战


UDP

【Socket网络编程进阶与实战】------- Socket UDP快速入门_第1张图片

为什么不可靠

【Socket网络编程进阶与实战】------- Socket UDP快速入门_第2张图片

能做什么

【Socket网络编程进阶与实战】------- Socket UDP快速入门_第3张图片

UDP包最大长度

【Socket网络编程进阶与实战】------- Socket UDP快速入门_第4张图片

核心API

API-DatagramSocket

【Socket网络编程进阶与实战】------- Socket UDP快速入门_第5张图片
【Socket网络编程进阶与实战】------- Socket UDP快速入门_第6张图片
【Socket网络编程进阶与实战】------- Socket UDP快速入门_第7张图片

API-DatagramPacket

【Socket网络编程进阶与实战】------- Socket UDP快速入门_第8张图片
【Socket网络编程进阶与实战】------- Socket UDP快速入门_第9张图片
【Socket网络编程进阶与实战】------- Socket UDP快速入门_第10张图片
【Socket网络编程进阶与实战】------- Socket UDP快速入门_第11张图片
【Socket网络编程进阶与实战】------- Socket UDP快速入门_第12张图片

UDP 单播、广播、多播

【Socket网络编程进阶与实战】------- Socket UDP快速入门_第13张图片

  • IP地址类别
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第14张图片
  • 广播地址
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第15张图片
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第16张图片
  • 广播地址运算
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第17张图片
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第18张图片
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第19张图片
  • 广播通信问题
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第20张图片

案例实操-局域网搜索案例

  • UDP接收消息并回送功能实现
  • UDP局域网广播发送实现
  • UDP局域网回送消息实现
package com.zcw.demo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * @ClassName : UDPProvider
 * @Description :UDP提供者,用于提供服务
 * @Author : Zhaocunwei
 * @Date: 2020-07-07 14:09
 */
public class UDPProvider {
    public static void main(String[] args) throws IOException {
        System.out.println("UDPProvider  Started.");
        //作为接收者,指定一个端口用于数据接收
        DatagramSocket ds = new DatagramSocket(20000);
        //构建接收实体
        final byte[] buf = new byte[512];
        DatagramPacket receivePack = new DatagramPacket(buf,buf.length);

        //接收
        ds.receive(receivePack);
        //打印接收到的信息与发送者的信息
        //发送者的IP地址
        String ip = receivePack.getAddress().getHostAddress();
        int port = receivePack.getPort();
        int dataLen = receivePack.getLength();
        String data = new String(receivePack.getData(),0,dataLen);
        System.out.println("UDPProvider receive form ip:"+ip
          +"\tport:"+port+"\tdata:"+data);

        //构建一份回送数据
        String responseData = "Receive data winth len:"+dataLen;
        byte[] responseDataBytes = responseData.getBytes();
        //直接根据发送者构建一份回送信息
        DatagramPacket responsePacket = new DatagramPacket(responseDataBytes,
                responseDataBytes.length,
                receivePack.getAddress(),
                receivePack.getPort());
        ds.send(responsePacket);
        //完成
        System.out.println("UDPProvider  Finished.");
        ds.close();
    }
}



package com.zcw.demo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * @ClassName : UDPSearcher
 * @Description : UDP 搜索,用于搜索服务支持方
 * @Author : Zhaocunwei
 * @Date: 2020-07-07 14:09
 */
public class UDPSearcher {
    public static void main(String[] args) throws IOException {
        System.out.println("UDPSearcher  Started.");
        //作为搜索方,让系统自动分配端口
        DatagramSocket ds = new DatagramSocket();

        //构建一份回送数据
        String requestData = "HelloWord:";
        byte[] requestDataBytes = requestData.getBytes();
        //直接根据发送者构建一份回送信息
        DatagramPacket requestPacket = new DatagramPacket(requestDataBytes,
                requestDataBytes.length);
        //本机端口20000
        requestPacket.setAddress(InetAddress.getLocalHost());
        requestPacket.setPort(20000);
        ds.send(requestPacket);


        //构建接收实体
        final byte[] buf = new byte[512];
        DatagramPacket receivePack = new DatagramPacket(buf,buf.length);

        //接收
        ds.receive(receivePack);
        //打印接收到的信息与发送者的信息
        //发送者的IP地址
        String ip = receivePack.getAddress().getHostAddress();
        int port = receivePack.getPort();
        int dataLen = receivePack.getLength();
        String data = new String(receivePack.getData(),0,dataLen);
        System.out.println("UDPSearcher receive form ip:"+ip
                +"\tport:"+port+"\tdata:"+data);


        //完成
        System.out.println("UDPSearcher  Finished.");
        ds.close();
    }
}

  • 测试:
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第21张图片
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第22张图片
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第23张图片

优化上面Demo

  • 创建消息创建者
package com.zcw.demo;

/**
 * @ClassName : MessageCreator
 * @Description :发送消息
 * @Author : Zhaocunwei
 * @Date: 2020-07-07 14:44
 */
public class MessageCreator {
    private static final String SN_HEADER="收到暗号,我是(SN):";
    private static final String PORT_HEADER="这是暗号,请回端口(Port):";

    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;
  }
}


  • 修改内容提供者
package com.zcw.demo;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.UUID;

/**
 * @ClassName : UDPProvider
 * @Description :UDP提供者,用于提供服务
 * @Author : Zhaocunwei
 * @Date: 2020-07-07 14:09
 */
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);
                    //打印接收到的信息与发送者的信息
                    //发送者的IP地址
                    String ip = receivePack.getAddress().getHostAddress();
                    int port = receivePack.getPort();
                    int dataLen = receivePack.getLength();
                    String data = new String(receivePack.getData(), 0, dataLen);
                    System.out.println("UDPProvider receive form ip:" + ip
                            + "\tport:" + port + "\tdata:" + data);

                    //解析端口号
                    int responsePort = MessageCreator.parsePort(data);
                    if (responsePort != -1) {

                        //构建一份回送数据
                        String responseData = MessageCreator.buildWithSn(sn);
                        byte[] responseDataBytes = responseData.getBytes();
                        //直接根据发送者构建一份回送信息
                        DatagramPacket responsePacket = new DatagramPacket(responseDataBytes,
                                responseDataBytes.length,
                                receivePack.getAddress(),
                                responsePort);
                        ds.send(responsePacket);
                    }
                }
            } catch (Exception ignored) {
            } finally {
                close();
            }
            //完成
            System.out.println("UDPProvider  Finished.");
        }

        private void close() {
            if (ds != null) {
                ds.close();
                ds = null;
            }
        }

        /**
         * 提供结束方法
         */
        void exit() {
            done = true;
            close();
        }
    }
}


  • 修改我们的数据搜索者

package com.zcw.demo;

import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @ClassName : UDPSearcher
 * @Description : UDP 搜索,用于搜索服务支持方
 * @Author : Zhaocunwei
 * @Date: 2020-07-07 14:09
 */
public class UDPSearcher {
    private static final int LISTEN_PORT=30000;

    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("UDPSearcher  Started.");

        Listener listen = listen();
        sendBroadcast();

        //读取任意键盘信息后可以退出
        System.in.read();
        List<Device> devices = listen.getDevicesAndClose();
        for (Device device :devices){
            System.out.println("Device:"+device.toString());

        }
        //完成
        System.out.println("UDPSearcher  Finished.");
    }

    private static Listener listen() throws InterruptedException {
        System.out.println("UDPSearcher  start listen.");
        CountDownLatch countDownLatch = new CountDownLatch(1);
        Listener listener = new Listener(LISTEN_PORT,countDownLatch);
        listener.start();
        countDownLatch.await();
        return listener;
    }

    private static void sendBroadcast() throws IOException {
        System.out.println("UDPSearcher sendBroadcast  Started.");
        //作为搜索方,让系统自动分配端口
        DatagramSocket ds = new DatagramSocket();

        //构建一份回送数据
        String requestData = MessageCreator.buildWithPort(LISTEN_PORT);
        byte[] requestDataBytes = requestData.getBytes();
        //直接根据发送者构建一份回送信息
        DatagramPacket requestPacket = new DatagramPacket(requestDataBytes,
                requestDataBytes.length);

        //20000端口,广播地址
        requestPacket.setAddress(InetAddress.getByName("255.255.255.255"));
        requestPacket.setPort(20000);
        ds.send(requestPacket);
        ds.close();

        //完成
        System.out.println("UDPSearcher  sendBroadcast Finished.");
    }
    private static class Device{
        final int port;
        final String ip;
        final String sn;

        private 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<Device>();
        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);
                   //打印接收到的信息与发送者的信息
                   //发送者的IP地址
                   String ip = receivePack.getAddress().getHostAddress();
                   int port = receivePack.getPort();
                   int dataLen = receivePack.getLength();
                   String data = new String(receivePack.getData(),0,dataLen);
                   System.out.println("UDPSearcher receive form ip:"+ip
                           +"\tport:"+port+"\tdata:"+data);

                   String sn = MessageCreator.parseSn(data);
                    if(sn!=null){
                        Device device = new Device(port,ip,sn);
                        devices.add(device);
                    }
               }
            }catch(Exception ignored){

            }finally {
                close();
            }
            System.out.println("UDPSearcher listener finished");
        }
        private void close(){
            if(ds!=null){
                ds.close();
                ds=null;
            }
        }
        List<Device> getDevicesAndClose(){
            done=true;
            close();
            return devices;
        }
    }
}


  • 测试:
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第24张图片
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第25张图片
    【Socket网络编程进阶与实战】------- Socket UDP快速入门_第26张图片

你可能感兴趣的:(Socket,socket,网络,UDP)