介绍在之前的系列文章中,我们使用netty作为聊天服务器,聊天服务器使用的SocketChannel,也就是说底层协议使用的是Scoket。今天我们就来给大家介绍下netty中UDP协议的使用方法。UDP协议UDP(UserDatagramProtocol),又称为UserDatagramProtocol。UDP的主要功能和亮点不在于它引入了什么特性,而在于它忽略了那些特性:不保证消息传递、不保证传递顺序、不跟踪连接状态、不需要拥塞控制。我们来看一下UDP数据包:UDP是一种无连接协议。发送方只需要发送数据包,不负责处理和保证数据是否成功发送或处理。它的唯一功能是发送。JDK中有一个专门针对UDP的类,叫做:java.net.DatagramPacket,NIO中还有一个java.nio.channels.DatagramChannel,负责处理UDP通道。这里我们将使用netty。Netty对于UDP协议也有以上两个类。虽然名称相同,但对应的包却不同。它们是:io.netty.channel.socket.DatagramPacket和io.netty.channel.socket.DatagramChannel。当然netty中的这两个类是对JDK自带类的增强。首先看netty中DatagramPacket的定义:publicclassDatagramPacketextendsDefaultAddressedEnvelopeimplementsByteBufHolderDatagramPacket类实现了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的编解码。这种处理只能处理String的转换,对Object无效。如果不想使用这些编码器和解码器,可以直接使用ByteBuf和String进行转换。例如,要将String写入ByteBuf,可以这样调用Unpooled.copiedBuffer:Unpooled.copiedBuffer("Startbroadcasting",CharsetUtil.UTF_8)要将ByteBuf转成String,可以调用:byteBuf.toString(CharsetUtil.UTF_8)构造DatagramPacketDatagramPacket总共可以接受三个参数,分别是要发送的数据、接收数据包的地址和发送数据包的地址。这里我们不关心发送数据包的地址,所以只需要两个参数。对于客户端,我们向服务器发送“开始广播”消息,告诉服务器向客户端发送回复消息。如下图:newDatagramPacket(Unpooled.copiedBuffer("Startbroadcasting",CharsetUtil.UTF_8),SocketUtils.socketAddress("255.255.255.255",PORT))我们使用SocketUtils.socketAddress创建一个特殊地址,255.255.255.255是一个特殊的广播地址,表示所有主机,因为我们的客户端不知道服务器的地址,所以我们使用255.255.255.255来广播。构造的DatagramPacket包含一个sender()方法,可以用来获取客户端的地址,所以要发送的数据包可以在服务端这样构造:newDatagramPacket(Unpooled.copiedBuffer("Broadcast:"+nextQuote(),CharsetUtil.UTF_8),packet.sender())startclientandserverUDPclientandserverstart与socket略有不同,如果是socket,那么使用的channel是NioSocketChannel,如果是UDP,则使用NioDatagramChannel。下面是启动服务器的代码:EventLoopGroupgroup=newNioEventLoopGroup();试试{Bootstrapb=newBootstrap();b.group(group).channel(NioDatagramChannel.class).option(ChannelOption.SO_BROADCAST,true).handler(newUDPServerHandler());b.bind(PORT).sync().channel().closeFuture().await();}最后{group.shutdownGracefully();注意,这里我们需要将ChannelOption.SO_BROADCAST设置为true,因为UDP是以广播的形式发送消息。客户端的实现与套接字略有不同。下面是客户端的启动实现:EventLoopGroupgroup=newNioEventLoopGroup();试试{Bootstrapb=newBootstrap();b.group(group).channel(NioDatagramChannel.class).option(ChannelOption.SO_BROADCAST,true).handler(newUDPClientHandler());Channelch=b.bind(0).sync().channel();对于UDP,没有地址绑定,所以去Bootstrap调用bind(0)。小结本文讲解了UDP协议在netty中的实现,比Socket连接简单。本文示例可参考:learn-netty4本文已收录于http://www.flydean.com/11-netty-udp/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!