简介

在之前的系列文章中,我们到了使用netty做聊天服务器,聊天服务器使用的SocketChannel,也就是说底层的协议使用的是Scoket。今天我们将会给大家介绍如何在netty中使用UDP协议。

UDP协议

UDP( User Datagram Protocol ),也叫用户数据报协议。

UDP 的主要功能和亮点并不在于它引入了什么特性,而在于它忽略的那些特性:不保证消息交付,不保证交付顺序,不跟踪连接状态,不需要拥塞控制。

我们来看一下UDP的数据包:

UDP是一种无连接的协议,发送者只管发送数据包即可,并不负责处理和保证数据是否成功发送,数据是否被处理完成等。它的唯一作用就是发送。

在JDK中表示UDP的有一个专门的类叫做:java.net.DatagramPacket,在NIO中还有一个java.nio.channels.DatagramChannel,专门负责处理UDP的channel。

这里我们要将的是netty,netty中对于UDP协议也有上面的两个类,名字虽然是一样的,但是对应的包不同。他们分别是:

io.netty.channel.socket.DatagramPacket 和 io.netty.channel.socket.DatagramChannel,当然netty中的这两个类是对JDK自带类的增强。

先看一下netty中DatagramPacket的定义:

public class DatagramPacket
extends DefaultAddressedEnvelope<ByteBuf, InetSocketAddress> implements ByteBufHolder

DatagramPacket类实现了ByteBufHolder接口,表示它里面存放的是ByteBuf。然后他又继承自DefaultAddressedEnvelope,这个类是对地址的封装,其中ByteBuf表示传递消息的类型,InetSocketAddress表示目标的地址,它是一个IP地址+端口号的封装。

从上面的UDP协议我们知道,UDP只需要知道目标地址和对应的消息即可,所以DatagramPacket中包含的数据已经够用了。

DatagramChannel是用来传递DatagramPacket的,因为DatagramChannel是一个接口,所以一般使用NioDatagramChannel作为真正使用的类。

String和ByteBuf的转换

之前我们讲到过,netty中的channel只接受ByteBuf数据类型,如果直接写入String会报错,之前的系列文章中,我们讲过两种处理方法,第一种是使用ObjectEncoder和ObjectDecoder在写入ByteBuf之前,对对象进行序列化,这一种不仅适合String,也适合Object对象。

第二种是使用StringEncoder和StringDecoder专门处理String的encode和decode,这种处理只能处理String的转换,对Object无效。

如果你不想使用这些encoder和decoder还可以直接使用ByteBuf和String进行转换。

比如要将String写入ByteBuf可以调用Unpooled.copiedBuffer的命令如下:

Unpooled.copiedBuffer("开始广播", CharsetUtil.UTF_8)

将ByteBuf转换成为String则可以调用:

byteBuf.toString(CharsetUtil.UTF_8)

构建DatagramPacket

DatagramPacket总共可以接受三个参数,分别是要发送的数据data,要接收数据包的地址和要发送数据包的地址。

这里我们并不关心发送数据包的地址,那么只需要两个参数即可,对于客户端来说,我们发送一个”开始广播“的消息给服务器端,告诉服务器端可以向客户发送回复消息了,如下所示:

new DatagramPacket(
Unpooled.copiedBuffer("开始广播", CharsetUtil.UTF_8),
SocketUtils.socketAddress("255.255.255.255", PORT))

上我们使用SocketUtils.socketAddress创建了一个特殊的地址,255.255.255.255是一个特殊的广播地址,意味着所有的主机,因为我们的客户端并不知道服务器的地址,所以使用255.255.255.255来广播。

构建好的DatagramPacket,里面有一个sender()方法,可以用来获取客户端的地址,所以在服务器端可以这样构建要发送的packge:

new DatagramPacket(
Unpooled.copiedBuffer("广播: " + nextQuote(), CharsetUtil.UTF_8), packet.sender())

启动客户端和服务器

UDP的客户端和服务器启动和socket稍微有所不同,如果是socket,那么使用的channel是NioSocketChannel,如果是UDP,则使用的是NioDatagramChannel。如下是服务器端启动的代码:

EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UDPServerHandler()); b.bind(PORT).sync().channel().closeFuture().await();
} finally {
group.shutdownGracefully();
}

注意,这里我们需要设置ChannelOption.SO_BROADCAST为true,因为UDP是以广播的形式发送消息的。

客户端的实现和socket稍微有所不同,下面是客户端的启动实现:

 EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_BROADCAST, true)
.handler(new UDPClientHandler()); Channel ch = b.bind(0).sync().channel();

对于UDP来说,并不存在地址绑定一说,所以上Bootstrap调用bind(0)。

总结

本文讲解了netty中UDP协议的实现,UDP相较于Socket连接而言更加简单。

本文的例子可以参考:learn-netty4

本文已收录于 http://www.flydean.com/11-netty-udp/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

netty系列之:使用UDP协议的更多相关文章

  1. netty 3.9.2 UDP协议服务器和客户端DEMO

    说明:基于netty 3.9.2的udp协议实现的(如果你使用的版本是4.X或5.X,请参考其他方法):程序的逻辑结构是,客户端发送给服务端一串数据,服务器端返回给客户端“A”.在进行游戏开发时需要对 ...

  2. netty系列之:kequeue传输协议详解

    目录 简介 KQueueEventLoopGroup KQueueEventLoop KQueueServerSocketChannel和KQueueSocketChannel 总结 简介 在前面的章 ...

  3. 没错,请求DNS服务器还可以使用UDP协议

    目录 简介 搭建netty客户端 在netty中发送DNS查询请求 DNS消息的处理 总结 简介 之前我们讲到了如何在netty中构建client向DNS服务器进行域名解析请求.使用的是最常见的TCP ...

  4. Netty 系列九(支持UDP协议).

    一.基础知识 UDP 协议相较于 TCP 协议的特点: 1.无连接协议,没有持久化连接:2.每个 UDP 数据报都是一个单独的传输单元:3.一定的数据报丢失:4.没有重传机制,也不管数据报是否可达:5 ...

  5. netty系列之:protobuf在UDP协议中的使用

    目录 简介 UDP在netty中的表示 DatagramPacketEncoder DatagramPacketDecoder 总结 简介 netty中提供的protobuf编码解码器可以让我们直接在 ...

  6. Netty4.x中文教程系列(七)UDP协议

    将近快一年时间没有更新Netty的博客.一方面原因是因为项目进度的问题.另外一方面是博主有一段时间去熟悉Unity3D引擎. 本章节主要记录博主自己Netty的UDP协议使用. 1. 构建UDP服务端 ...

  7. netty系列之: 在netty中使用 tls 协议请求 DNS 服务器

    目录 简介 支持DoT的DNS服务器 搭建支持DoT的netty客户端 TLS的客户端请求 总结 简介 在前面的文章中我们讲过了如何在netty中构造客户端分别使用tcp和udp协议向DNS服务器请求 ...

  8. 协议系列UDP协议

    所述上部TCP虽然该协议提供了一个可靠的传输,但也有一个缺点.发送速度慢.是否有协议它可以以高速传送?这部分是将要讨论UDP协议,它提供了更加快了传输速度.而且在可靠性为代价,这是一个无连接的传输协议 ...

  9. 协议系列之UDP协议

    上节说的TCP协议虽然提供了可靠的传输,但是也有一个缺点,发送速度慢.那么有没有一种协议能快速发送的呢?这节要讨论的就是UDP协议,它提供了更加快的发送速度,但也牺牲了可靠性,它是一种无连接的传输协议 ...

随机推荐

  1. 8、ITSM基本概念(1)

    ITSM即是信息技术服务管理: 8.1.什么是服务: 8.2.RACI模型: 谁负责(R =n Resposible),即负责执行任务的角色,他/她具体负责操控项目.解决问题. 谁批准(A = Acc ...

  2. 9.5、zabbix高级操作(2)

    4.zabbix的分布式监控: 使用zabbix-proxy主动方式(被动也可),使用zabbix-agent的主动方式(被动也可): Zabbix Server <- Zabbix Proxy ...

  3. 浅读tomcat架构设计之tomcat生命周期(2)

    浅读tomcat架构设计和tomcat启动过程(1) https://www.cnblogs.com/piaomiaohongchen/p/14977272.html tomcat通过org.apac ...

  4. 如何跟领导解释为什么选择SpringCloud alibaba作为微服务开发框架

    什么是微服务 提到微服务不得不提Martin Fowler在2014年3月25日发表的文章 Microservices,里面给出了微服务的定义.后续国内所有关于微服务的介绍都是基于这篇文章的翻译,或加 ...

  5. Python实现 利用朴素贝叶斯模型(NBC)进行问句意图分类

    目录 朴素贝叶斯分类(NBC) 程序简介 分类流程 字典(dict)构造:用于jieba分词和槽值替换 数据集构建 代码分析 另外:点击右下角魔法阵上的[显示目录],可以导航~~ 朴素贝叶斯分类(NB ...

  6. Vue数据双向绑定不起作用、Vue如何正确的手动添加json数据、Vue视图层不刷新、手动刷新视图层

    Vue.set(obj,"key","value") 如果接收到来自服务器的消息时,我们需要对其进性进一步处理 我们想当然的会直接将数据添加进json 像这样: ...

  7. Python基础4--数据类型

    一.数据类型是什么鬼? 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同 ...

  8. Min25 筛学习笔记

    仅仅是 \(min25\) 筛最基本的方法,没有任何推式子的例题.(想了想还是加两道吧qwq) 这里解决的是 \(Luogu\) 那道模板题. min25 基本方法: 最基础的是两个式子: \[G(n ...

  9. [刘阳Java]_Spring对Dao的支持_第10讲

    Spring框架优秀就是在于MVC开发的时候一旦需要对底层的数据库操作,它可以很好的支持JDBC技术,还有现在主流的ORM框架(Hibernate, MyBatis)技术. 重点先介绍Spring对J ...

  10. 【学习笔记】Tensor多维数组和axis的理解

    Tensor多维数组和axis的理解 今天在编写程序的时候一直对于axis=0或等于1搞不明白,这样对于整个numpy或者是tensorflow的基本运算和数据处理都会很模糊,所以花了一些时间来搞清楚 ...