《Netty实战》读书笔记——编解码器与网络协议
编解码器
解码器
- 将字节解码为消息——
ByteToMessageDecoder
和ReplayingDecoder
; - 将一种消息类型解码为另一种——
MessageToMessageDecoder
io.netty.handler.codec.LineBasedFrameDecoder
:这个类在Netty 内部 也有使用,它使用了行尾控制字符(\n
或者\r\n
)来解析消息数据;
io.netty.handler.codec.http.HttpObjectDecoder
:一个HTTP 数据的解码器。在io.netty.handler.codec
子包下面,你将会发现更多用于特定用例的编码器和解码器实现。
Netty 提供了TooLongFrameException
类,其将由解码器在帧超出指定的大小限制时抛出。
编码器
MessageToByteEncoder
:encode()
方法是你需要实现的唯一抽象方法。它被调用时将会传入要被该类编码为ByteBuf
的出站消息。该ByteBuf 随后将会被转发给ChannelPipeline
中的下一个ChannelOutboundHandler
MessageToMessageEncoder
:出站数据将如何从一种消息编码为另一种
编解码器
ByteToMessageCodec
:我们需要将字节解码为某种形式的消息,可能是POJO
,随后再次对它进行编码。ByteToMessageCodec
将为我们处理好这一切,因为它结合了ByteToMessageDecoder
以及它的逆向——MessageToByteEncoder
MessageToMessageCodec
:将一种消息格式转换为另外一种消息格式,可以在一个单个的类中实现该转换的往返过程
CombinedChannelDuplexHandler
:这个类充当了ChannelInboundHandler
和ChannelOutboundHandler
的容器。通过提供分别继承了解码器类和编码器类的类型,我们可以实现一个编解码器,而 又不必直接扩展抽象的编解码器类。
Web协议
SslChannelHandler
public class SslChannelInitializer extends ChannelInitializer<Channel> {
private final SslContext context;
private final boolean startTls;
public SslChannelInitializer(SslContext context, boolean startTls) {
// 传入要使用的SslContext
this.context = context;
// 如果设置为true,第一个写入的消息将不会被加密(客户端应该设置为true)
this.startTls = startTls;
}
@Override
protected void initChannel(Channel ch) throws Exception {
// 对于每个SslHandler实例,都从SslContext获取一个新的SSLEngine
SSLEngine engine = context.newEngine(ch.alloc());
// 将SslHandler作为第一个ChannelHandler添加到ChannelPipeline中
ch.pipeline().addFirst("ssl", new SslHandler(engine, startTls));
}
}
HttpObjectAggregator
:聚合HTTP消息
HTTP压缩:
HttpContentDecompressor
(客户端使用)HttpContentCompressor
(服务端使用)
public class HttpPipelineInitializer extends ChannelInitializer<Channel> {
private final boolean isClient;
public HttpPipelineInitializer(boolean isClient) {
this.isClient = isClient;
}
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 方法一:分别添加编码器与解码器
if (isClient) {
pipeline.addLast("decoder", new HttpResponseDecoder());
pipeline.addLast("encoder", new HttpRequestEncoder());
} else {
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
}
// 方法二:直接添加编解码器
if (isClient) {
pipeline.addLast("codec", new HttpClientCodec());
} else {
pipeline.addLast("codec", new HttpServerCodec());
}
// 聚合HTTP消息
pipeline.addLast("aggregator", new HttpObjectAggregator(512 * 1024));
// HTTP压缩
if (isClient) {
pipeline.addLast("decompressor", new HttpContentDecompressor());
} else {
pipeline.addLast("compressor", new HttpContentCompressor());
}
}
}