简介UDT是一个非常优秀的协议,它可以提供基于UDP协议的高速数据传输。但遗憾的是在netty4.1.7中,UDT传输协议已经被标记为Deprecated!意味着在以后的netty版本中,你可能再也见不到UDT协议了。一个优秀的协议如何被埋没,让我们揭开UDT的面纱,展现其优秀的特性,让netty重新爱上UDT。Netty对UDT的支持Netty对UDT的支持体现在一个特殊的UDT包中,用来处理UDT相关的事情:packageio.netty.channel.udt。这个包主要定义了各种UDT通道,通道配置,UDT消息,以及提供ChannelFactory和SelectorProvider的工具类NioUdtProvider。构建支持UDT的netty服务遵循netty的标准流程。现在是创建netty服务的时候了。.在netty中创建服务器服务无非就是创建EventLoop,创建ServerBootstrap,绑定EventLoop,指定通道类型。这很简单。唯一不同的是具体的childHandler,可能会根据具体的协议使用不同的处理方式。当然如果不是NioSocketChannel,相应的ChannelFactory和SelectorProvider也会发生变化。没有关系,我们先看看下面如何创建支持UDT的netty服务:finalThreadFactoryacceptFactory=newDefaultThreadFactory("accept");finalThreadFactoryconnectFactory=newDefaultThreadFactory("connect");finalNioEventLoopGroupacceptGroup=newNioEventLoopGroup(1,acceptFactory,NioUdtProvider.BYTE_PROVIDER);finalNioEventLoopGroupconnectGroup=newNioEventLoopGroup(1,connectFactory,NioUdtProvider.BYTE_PROVIDER);finalServerBootstrapboot=newServerBootstrap();boot.group(acceptGroup,connectGroup).channelFactory(NioUdtProvider.BYTE_ACCEPTOR).option(ChannelOption.SO_BACKLOG,10).handler(newLoggingHandler(LogLevel.INFO)).childHandler(newChannelInitializer(){@OverridepublicvoidinitChannel(finalUdtChannelch){ch.pipeline().addLast(新的LoggingHandler(LogLevel.INFO),新的UDTEchoServerHandler());}});//启动服务finalChannelFuturefuture=boot.bind(PORT).sync();可以看到UDT不同于普通的nettysocket服务,它的selector和channelFactory都是由NioUdtProvider提供的。NioUdtProvider是netty核心包中的内容。它为UDT提供了一个有用的包。我们不需要太了解UDT的内部实现就可以使用UDT协议。是的,不是很精彩。异常发生。如果有朋友兴冲冲的拿着上面的代码尝试运行,很遗憾会得到一个异常。异常大概类似于下面的情况:找不到包com.barchart.udt!什么?直接使用netty包中的类会报错吗?是可忍还是不可忍!我们仔细分析一下。这里只有一个新类,就是NioUdtProvider。打开NioUdtProvider的源代码。在导入一栏,我们突然发现引用了不属于netty的包,这些包报错:importcom.barchart.udt。SocketUDT;导入com.barchart.udt.TypeUDT;导入com.barchart.udt.nio.ChannelUDT;导入com.barchart.udt.nio.KindUDT;导入com.barchart.udt.nio.RendezvousChannelUDT;导入com.barchart.udt.nio.SelectorProviderUDT;虽然很奇怪,但是我们要想程序运行起来还是需要找到这些依赖包。经过自己的跋涉,翻山越水,功夫终于有了回报。找到以下依赖包:com.barchart.udtbarchart-udt-core2.3.0com.barchart.udtbarchart-udt-bundle2.3.0netty核心包其实依赖第三方库,这可能是netty要取消对UDT支持的原因。TypeUDT和KindUDT如果你去查看barchart中类的具体信息,你会发现这个包的作者有一个习惯,就是在类后面放一个UDT。当你看到屏幕上所有的类都以UDT结尾时,没错,就是nettyUDT依赖的barchart包。不能说大牛们开发的包不好,只能说看着有点累....barchart包中有两个核心类区分UDT类型和种类,分别叫TypeUDT和KindUDT分别.Type和kind翻译成中文好像区别不大。但是两者在UDT上还是有很大区别的。TypeUDT表示UDT套接字的模式。它有两个值,分别是流和数据报:STREAM(1)、DATAGRAM(2),表示数据传输是以字节流的形式还是以数据报消息的格式。KindUDT用于区分服务器和客户端。它有三种模式:ACCEPTOR,CONNECTOR,RENDEZVOUS服务器模式对应ACCEPTOR,用于监听和接收连接。它的代表是ServerSocketChannelUDT,通过调用accept()方法返回一个CONNECTOR.CONNECTOR模式,在客户端和服务端都可以使用。它的代表类是SocketChannelUDT。如果在服务器端,则通过调用服务器端的accept方法生成。如果是在client端,就是client端和server端的连接。另一种模式是RENDEZVOUS模式。这种模式意味着连接的每一端都有对称的对等通道。它是一种双向模式,它的代表类是RendezvousChannelUDT。构建ChannelFactory上面提到的2个Type和3个Kind都是用来定义channel的,所以如果混合使用,会生成6个不同的channelFactory,即:publicstaticfinalChannelFactoryBYTE_ACCEPTOR=newNioUdtProvider(TypeUDT.STREAM,KindUDT.ACCEPTOR);publicstaticfinalChannelFactoryBYTE_CONNECTOR=newNioUdtProvider(TypeUDT.STREAM,KindUDT.CONNECTOR);publicstaticfinalChannelFactoryBYTE_RENDEZVOUS=newNioUdtProvider(TypeUDT.STREAM,KindUDT。RENDEZVOUS);publicstaticfinalChannelFactoryMESSAGE_ACCEPTOR=newNioUdtProvider(TypeUDT.DATAGRAM,KindUDT.ACCEPTOR);publicstaticfinalChannelFactoryMESSAGE_CONNECTOR=newNioUdtProvider(类型UDT.DATAGRAM,KindUDT.CONNECTOR);publicstaticfinalChannelFactoryMESSAGE_RENDEZVOUS=newNioUdtProvider(TypeUDT.DATAGRAM,KindUDT.RENDEZVOUS);这些channelFactory通过调用newChannel()方法生成新的通道,但返回到根节点。这些通道最终是通过调用SelectorProviderUDT的from方法生成的。SelectorProviderUDTSelectorProviderUDT根据TypeUDT有两种,分别是:publicstaticfinalSelectorProviderUDTDATAGRAM=newSelectorProviderUDT(TypeUDT.DATAGRAM);publicstaticfinalSelectorProviderUDTSTREAM=newSelectorProviderUDT(TypeUDT.STREAM);调用他可以生成三个方法对应的channel:publicRendezvousChannelUDTopenRendezvousChannel()throwsIOException{finalSocketUDTsocketUDT=newSocketUDT(type);返回新的RendezvousChannelUDT(this,socketUDT);}publicServerSocketChannelUDTopenServerSocketChannel()throwsIOException{finalSocketUDTserverSocketUDT=newSocketUDT(type);返回新的ServerSocketChannelUDT(this,serverSocketUDT);}publicSocketChannelUDTopenSocketChannel()throwsIOException{finalSocketUDTsocketUDT=newSocketUDT(type);returnnewSocketChannelUDT(这个,socketUDT是用来搭建服务器的);处理程序处理数据。这里我们简单的将客户端写入的数据写回。客户端首先创建一条消息:message=Unpooled.buffer(UDTEchoClient.SIZE);message.writeBytes("www.flydean.com".getBytes(StandardCharsets.UTF_8));然后写入服务器:ctx.writeAndFlush(消息);}服务端通过channelRead方法接收:publicvoidchannelRead(finalChannelHandlerContextctx,Objectmsg){ctx.write(msg);}总结以上就是在netty中使用UDT的原理和一个简单的例子。本文示例可参考:learn-netty4本文已收录于http://www.flydean.com/40-netty-udt-support/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!