前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Netty】UDP协议使用学习

【Netty】UDP协议使用学习

作者头像
冷环渊
发布2022-05-01 14:05:43
1.3K0
发布2022-05-01 14:05:43
举报
文章被收录于专栏:冷环渊的全栈工程师历程

UDP

传输层协议 :User Datagram Protocal

基于报文传输

分类

TCP

UDP

面向连接

无连接

只有两端 只能一对一通信

可以一对一,一对多,多对一,多对多通信

基于字节流

基于报文

重要特性

可靠

不可爱(尽最大可能交付)

首部占用空间大 20-60字节之间

首部空间小,8字节(记录报文长度)

UDP的分类

  • 单播: 一对一
  • 组播:一对多(组播)
  • 广播 : 多对多(局域网内的全部)

TCP协议已经尽可能的支持了并发 所以大部分还是使用的TCP协议 除非网络很差的情况下使用UDP

原生的UDP实现

  1. DatagramSocket 代表通信的一段
  2. DatagramPacket 是数据的通信格式 报文,
    1. 在创建的时候 需要明确数据是字节数组 以及另一端的ip地址+端口
    2. 在接受报文和发送报文前 使用字节数组进行接收和组装
  3. socket 去接受和发送时,对应receive()和 send() 方法

服务端

代码语言:javascript
复制
public class udpServer {
    public static void main(String[] args) throws Exception {

        //DatagramSocket - 用来建立连接,通信的一端
        DatagramSocket socket = new DatagramSocket(6789);
        //DatagramPacket - 报文
        DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
        while (true) {
            socket.receive(packet);
            byte[] msg = Arrays.copyOfRange(packet.getData(), packet.getOffset(), packet.getOffset() + packet.getLength());
            System.out.println("Receive data" + new String(msg));
            System.out.println("Receive data Form" + packet.getAddress().getHostAddress());
            socket.send(packet);
        }
    }
}

客户端

代码语言:javascript
复制
//单播的通信方式
public class udpClient {
    public static void main(String[] args) throws Exception {
        //如果使用多播 使用  MulticastSocket
        DatagramSocket socket = new DatagramSocket();
        InetAddress localHost = InetAddress.getLocalHost();
        SocketAddress socketAddress = new InetSocketAddress(localHost, 6789);
        byte[] msg = new String("hello udp server").getBytes();
        DatagramPacket packet = new DatagramPacket(msg, msg.length, socketAddress);
        socket.send(packet);
        socket.close();
    }
}

Netty的UDP实现

  1. DatagramSocket 对应 NioDatagramChannel
  2. java.net.datagramPacket 对应 import io.netty.channel.socket.DatagramPacket
  3. 无论客户端还是服务端都使用 bootstrap来启动
  4. 通过调用Bootstrap的localAddress()指定端口号,也可以调用remoeteAddress指定连接地址(ip+端口号)
  5. 自定义 handler 的使用 ,继承SimpleChannelInboundHandler 泛型声明为datagramPacket 实现channelread0方法来实现逻辑
  6. 组装datagramPacket 通过byteBuf 加上socketAddress()
  7. 组装bytebuf 调用Unplooled工具类 copiedbuffer方法 明确字符串和编码格式

服务端

代码语言:javascript
复制
public class udpNettyServer {
    public static void main(String[] args) {
        EventLoopGroup group = new NioEventLoopGroup();
        //可以统一使用bootstrap进行配置
        Bootstrap bootstrap = new Bootstrap();
        //实现udp协议 使用的通道
        bootstrap.group(group).channel(NioDatagramChannel.class)
                .localAddress(6789)
                .handler(new UdpServerHandler());
        try {
            ChannelFuture future = bootstrap.bind(6789).sync();
            future.channel().closeFuture().await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }
}

//DatagramPacket 使用的是netty包下的
class UdpServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
        System.out.println("receive packet" + datagramPacket.content().toString());
        ByteBuf buf = Unpooled.copiedBuffer("Sth", CharsetUtil.UTF_8);
        //通过组装bytebuf 获取发送报文的发送者 得到要返回的报文
        DatagramPacket packet = new DatagramPacket(buf, datagramPacket.sender());
        channelHandlerContext.writeAndFlush(packet);
    }
}

客户端

代码语言:javascript
复制
public class udpNettyClient {
    public static void main(String[] args) {
        EventLoopGroup group = new NioEventLoopGroup();
        //可以统一使用bootstrap进行配置
        Bootstrap bootstrap = new Bootstrap();
        //实现udp协议 使用的通道
        bootstrap.group(group).channel(NioDatagramChannel.class)
                .remoteAddress("127.0.0.1", 6789)
                .handler(new udpClientHandler());
        try {
            Channel channel = bootstrap.bind(0).sync().channel();
            ByteBuf buf = Unpooled.copiedBuffer("Send sth", CharsetUtil.UTF_8);
            //通过组装bytebuf 获取发送报文的发送者 得到要返回的报文
            DatagramPacket packet = new DatagramPacket(buf, SocketUtils.socketAddress("127.0.0.1", 6789));
            channel.writeAndFlush(packet).sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }
}

class udpClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
        String resp = datagramPacket.content().toString(CharsetUtil.UTF_8);
        System.out.println(resp);
        channelHandlerContext.close();
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022/04/30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • UDP
    • 原生的UDP实现
      • Netty的UDP实现
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档