共计 3109 个字符,预计需要花费 8 分钟才能阅读完成。
简介
UDT 给了你两种抉择,byte stream 或者 message, 到底选哪一种呢?教训通知咱们,只有小学生才做选择题,而咱们应该全都要!
类型的定义
UDT 的两种类型是怎么定义的呢?
翻看 com.barchart.udt 包,能够发现这两种类型定义在 TypeUDT 枚举类中。
STREAM(1),
DATAGRAM(2),
一个叫做 STREAM,它的 code 是 1。一个叫做 DATAGRAM,他的 code 是 2.
依据两个不同的类型咱们能够创立不同的 selectorProvider 和 channelFactory。而这两个正是构建 netty 服务所须要的。
在 NioUdtProvider 这个工具类中,netty 为咱们提供了 TypeUDT 和 KindUDT 的六种组合 ChannelFactory,他们别离是:
用于 Stream 的:BYTE_ACCEPTOR,BYTE_CONNECTOR,BYTE_RENDEZVOUS。
和用于 Message 的:MESSAGE_ACCEPTOR,MESSAGE_CONNECTOR 和 MESSAGE_RENDEZVOUS。
同样的,还有两个对应的 SelectorProvider, 别离是:
BYTE_PROVIDER 和 MESSAGE_PROVIDER.
搭建 UDT stream 服务器
如果要搭建 UDT stream 服务器,首先须要应用 NioUdtProvider.BYTE_PROVIDER 来创立 NioEventLoopGroup:
final NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.BYTE_PROVIDER);
final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, connectFactory, NioUdtProvider.BYTE_PROVIDER);
这里,咱们创立两个 eventLoop,别离是 acceptLoop 和 connectLoop。
接下来就是在 ServerBootstrap 中绑定下面的两个 group,并且指定 channelFactory。这里咱们须要 NioUdtProvider.BYTE_ACCEPTOR:
final ServerBootstrap boot = new ServerBootstrap();
boot.group(acceptGroup, connectGroup)
.channelFactory(NioUdtProvider.BYTE_ACCEPTOR)
.option(ChannelOption.SO_BACKLOG, 10)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<UdtChannel>() {
@Override
public void initChannel(final UdtChannel ch) {ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO),
new UDTByteEchoServerHandler());
}
});
就这么简略。
搭建 UDT message 服务器
搭建 UDT message 服务器的步骤和 stream 很相似,不同的是须要应用 NioUdtProvider.MESSAGE_PROVIDER 作为 selectorProvider:
final NioEventLoopGroup acceptGroup =
new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.MESSAGE_PROVIDER);
final NioEventLoopGroup connectGroup =
new NioEventLoopGroup(1, connectFactory, NioUdtProvider.MESSAGE_PROVIDER);
而后在绑定 ServerBootstrap 的时候应用 NioUdtProvider.MESSAGE_ACCEPTOR 作为 channelFactory:
final ServerBootstrap boot = new ServerBootstrap();
boot.group(acceptGroup, connectGroup)
.channelFactory(NioUdtProvider.MESSAGE_ACCEPTOR)
.option(ChannelOption.SO_BACKLOG, 10)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<UdtChannel>() {
@Override
public void initChannel(final UdtChannel ch)
throws Exception {ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO),
new UDTMsgEchoServerHandler());
}
});
同样很简略。
Stream 和 Message 的 handler
不同的 UDT 类型,须要应用不同的 handler。
对于 Stream 来说,它的底层是 byte, 所以咱们的音讯解决也是以 byte 的模式进行的, 咱们以上面的形式来构建 message:
private final ByteBuf message;
message = Unpooled.buffer(UDTByteEchoClient.SIZE);
message.writeBytes("www.flydean.com".getBytes(StandardCharsets.UTF_8));
而后应用 ctx.writeAndFlush(message) 将其写入到 channel 中。
对于 message 来说,它实际上格局对 ByteBuf 的封装。netty 中有个对应的类叫做 UdtMessage:
public final class UdtMessage extends DefaultByteBufHolder
UdtMessage 是一个 ByteBufHolder,所以它实际上是一个 ByteBuf 的封装。
咱们须要将 ByteBuf 封装成 UdtMessage:
private final UdtMessage message;
final ByteBuf byteBuf = Unpooled.buffer(UDTMsgEchoClient.SIZE);
byteBuf.writeBytes("www.flydean.com".getBytes(StandardCharsets.UTF_8));
message = new UdtMessage(byteBuf);
而后将这个 UdtMessage 发送到 channel 中:
ctx.writeAndFlush(message);
这样你就学会了在 UDT 协定中应用 stream 和 message 两种数据类型了。
总结
大家可能感觉不同的数据类型原来实现起来这么简略。这全都要归功于 netty 优良的封装和设计。
感激 netty!
本文的例子能够参考:learn-netty4
本文已收录于 http://www.flydean.com/40-netty-udt-support-2/
最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!
欢送关注我的公众号:「程序那些事」, 懂技术,更懂你!