Netty(4)之UDP协议开发

UDP协议开发

1. 概述

UDP 用户数据协议(User Datagram Protocol)

2. 作用

将网络流量压缩成数据报形式,提供面向事务的简单信息传输服务,利用IP协议进行数据报传输,提供无连接的、不可靠的数据投递服务

3. 特点

资源消耗小、处理速度快,通常使用在视频、音频等可靠性要求不高的数据传输

  • UDP是无连接的,发送方和接收方相互交换信息使双方同步
  • UDP接受到后不发送确认信息,发送端不知道是否成功,也不会重发
  • UDP传送数据比TCP快,系统开销小,常用于视频、图片以及简单文件传输系统。TCP适合于FTP文件传输系统、超文本传输协议HTTP、简单邮件传输协议SMTP等

4. 协议简介

UDP不需要简历物理链接。在网络中它用于处理数据包,在OSI模型中,它处理第四层传输层,即位于IP协议的上层

4.1 协议格式

分为两个部分:首部和数据

  • 源端口:源端口号,2个字节
  • 目的端口:目的端口号,2个字节
  • 长度:2字节,UDP用户数据报的总长度
  • 校验和:2个字节,用来验证数据字段和头部的“伪首部”

伪首部:在TCP或UDP的数据报格式中,在数据报首部前面增加源IP地址、目的IP地址、IP分组的协议字段、TCP或UDP数据报的总长度,共12字节。只为了保证可以校验套接字的正确性

Netty(4)之UDP协议开发_第1张图片

5. 代码实例

5.1 服务端

由于UDP协议不需要跟服务端进行连接,所以需要设置UDP为支持广播数据;并且使用 NioDatagramChannel.class 管道

public void bind(int port) {
        NioEventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap
                .group(workGroup)
                .channel(NioDatagramChannel.class)
                //设置Socket参数支持广播
                .option(ChannelOption.SO_BROADCAST, true)
                .handler(new ChineseProverbHandler());
            bootstrap.bind(port).channel().closeFuture().await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            workGroup.shutdownGracefully();
        }
    }
public class ChineseProverbHandler extends SimpleChannelInboundHandler<DatagramPacket> {

        private static final String[] DICTIONARY = {"只要功夫深,铁棒磨成针。", "洛阳亲友如想问,一片冰心在玉壶"};

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
            //将内容转换为字符串
            String req = msg.content().toString(StandardCharsets.UTF_8);
            System.out.println("请求数据:" + req);
            if ("谚语字典查询?".equals(req)) {
                ByteBuf byteBuf = Unpooled.copiedBuffer("谚语查询结果:" + nextQuote(), StandardCharsets.UTF_8);
                // msg.sender() 获取发送的ip和端口
                DatagramPacket returnPacket = new DatagramPacket(byteBuf, msg.sender());
                ctx.writeAndFlush(returnPacket);
            }
        }
        private String nextQuote() {
            //可能会出现并发问题
            int nextInt = ThreadLocalRandom.current().nextInt(DICTIONARY.length);
            return DICTIONARY[nextInt];
        }
    }

5.2 客户端

public void run(int port) {
        NioEventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap
                .group(workGroup)
                .channel(NioDatagramChannel.class)
                //设置Socket参数支持广播
                .option(ChannelOption.SO_BROADCAST, true)
                .handler(new ChineseProverbHandler());
            Channel channel = bootstrap.bind(0).sync().channel();
            //向网段内所有机器广播UDP消息
            channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("谚语字典查询?", StandardCharsets.UTF_8),
                                                     new InetSocketAddress("255.255.255.255", port))).sync();
            //等待15秒用于接受返回数据,然后退出
            if (!channel.closeFuture().await(15000)) {
                System.out.println("查询超时!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            workGroup.shutdownGracefully();
        }
    }
public class ChineseProverbHandler extends SimpleChannelInboundHandler<DatagramPacket> {

        @Override
        protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
            //将内容转换为字符串
            String response = msg.content().toString(StandardCharsets.UTF_8);
            if (response.startsWith("谚语查询结果:")) {
                System.out.println(response);
                ctx.close();
            }
        }
    }

你可能感兴趣的:(Netty,java,netty,UDP)