扫描下方二维码或者微信搜索公众号
菜鸟飞呀飞
,即可关注微信公众号,阅读更多Spring源码分析
和Java并发编程
文章。
前言
前两篇文章中分析了 netty 中解码器相关的源码,解码过程是发生在读数据这一步的,那么读到数据,经过解码器解码后,最终就会交由我们自定义的业务处理中执行,当我们的业务逻辑处理完成后,就需要给客户端响应消息,这就涉及到服务端如何通过 channel 将响应消息写出去的流程了,同时还会涉及到消息的编码过程,因为在 TCP 协议中,数据最终是通过字节流传输的,而我们通常在业务代码中是返回一个对象,因此需要进行编码。接下来本文将会重点分析这两个的过程的源码实现。
Demo 代码
为了方便描述,这里模拟一个简单的场景:netty 服务端在读到客户端发来的消息后,netty 服务端就通过我们自定义的 ChannelHandler 来进行业务处理,并返回一个 Data 对象,Data 类是我们自定义的一个类,然后我们将 Data 对象通过我们自定义的一个编码器 DataEncoder 进行编码,最后将消息发送出去。
netty 服务端启动的 demo 代码
public static void main(String[] args) throws InterruptedException {
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
NioEventLoopGroup workerGroup = new NioEventLoopGroup(8);
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.channel(NioServerSocketChannel.class)
.group(bossGroup,workerGroup)
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 向客户端channel中添加两个channelHandler
pipeline.addLast(new DataEncoder());
pipeline.addLast(new BusinessHandler());
}
});
serverBootstrap.bind(8080).sync();
}
可以看到,分别向客户端的 channel 的 pipeline 中添加了两个 ChannelHandler:DataEncoder 是自定义的一个编码器,负责进行编码,BusinessHandler 是负责进行业务处理的。因此创建出来的客户端 channel 的 pipeline 的结构如下,这个结构很重要,后面的源码分析全是基于这个结构来分析的。
DataEncoder 编码器的源码
/**
* 实际上就是一个基于换行符的编码器
*/
public class DataEncoder extends MessageToByteEncoder<Data> {
private static final String LINE = "\r\n";
@Override
protected void encode(ChannelHandlerContext ctx, Data msg, ByteBuf out) throws Exception {
if(msg instanceof Data){
out.writeBytes(msg.getMsg().getBytes());
out.writeLong(msg.getServerTime());
out.writeBytes(LINE.getBytes());
}
}
}
为了简化分析,BusinessHandler 的代码比较简单,它就是直接向客户端返回一个 Data 对象
public class BusinessHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {