【Netty】UDP协议使用学习

📣 📣 📣 📢📢📢
☀️☀️你好啊!小伙伴,我是小冷。是一个兴趣驱动自学练习两年半的的Java工程师。
📒 一位十分喜欢将知识分享出来的Java博主⭐️⭐️⭐️,擅长使用Java技术开发web项目和工具
📒 文章内容丰富:覆盖大部分java必学技术栈,前端,计算机基础,容器等方面的文章
📒 如果你也对Java感兴趣,关注小冷吧,一起探索Java技术的生态与进步,一起讨论Java技术的使用与学习
✏️高质量技术专栏专栏链接: 微服务数据结构netty单点登录SSMSpringCloudAlibaba
😝公众号😝想全栈的小冷,分享一些技术上的文章,以及解决问题的经验
当前专栏Netty 实战系列
专栏代码地址: Netty练手项目仓库地址

UDP

传输层协议 :User Datagram Protocal

基于报文传输

分类TCPUDP
面向连接无连接
只有两端 只能一对一通信可以一对一,一对多,多对一,多对多通信
基于字节流基于报文
重要特性可靠不可爱(尽最大可能交付)
首部占用空间大 20-60字节之间首部空间小,8字节(记录报文长度)

UDP的分类

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

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

原生的UDP实现

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

服务端

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

客户端

//单播的通信方式
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方法 明确字符串和编码格式

服务端

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

客户端

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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷环渊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值