文章目录
一、Netty ChannelHanlder
Netty组件包括了 Channel
ChannelHanlder
EventLoop
ChannelPipeline
等。
其中,Netty 的ChannelHandler
是处理出入站数据应用程序逻辑的实现者。常见的使用姿势是继承 ChannelInboundHandlerAdapter
ChannelOutboundHandlerAdapter
SimpleChannelInboundHandler
等类,而不是自己去实现一个ChannelHandler
。
``
二、ChannelPipeline
ChannelPipeline
就是 ChannelHandler
的链
其实出、入 (Outbound Inbound)也很好理解,拿客户端来说, 入就是 从服务端–> 客户端的数据 ; 出就是 客户端 --> 服务端的数据。
三、Codec
入站需要将二进制字节–> Java对象 ,需要指定Decoder
;
出站需要将Java对象 --> 二进制字节,需要指定Encoder
。
Netty内已经内置了很多实用的编解码器,开箱即用,最典型如StringEncoder
StringDecoder
。Codec
本质上也是 ChannelHandler
。所以说,ChannelHandler
,更准确说ChannelInboundHandler
、ChannelOutboundHandler
,为处理出入站事件(数据)提供了统一抽象。
3.1 ByteToMessageDecoder解码器
ByteToMessageDecoder
的 java doc
:
ChannelInboundHandlerAdapter which decodes bytes in a stream-
like fashion from one ByteBuf to an other Message type. For example
here is an implementation which reads all readable bytes from the
input ByteBuf and create a new ByteBuf.
public class SquareDecoder extends ByteToMessageDecoder {
@Override
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
throws Exception {
out.add(in.readBytes(in.readableBytes()));
}
}
换成人话就是:由于不知道远程接地那是否一次性发送一个完整信息,TCP存在粘包拆包问题。Byte2MessageDedocer
会对入站数据缓冲,直到数据ready.
搞一个最简单的demo:
// 一个整数 四个字节,这样就相当于定义了一个协议
public class ToIntegerDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.readableBytes() >= 4) {
out.add(in.readInt());
}
}
}
四、ReplayingDecoder
ReplayingDecoder
扩展了 ByteToMessageDecoder
,使用这个类,不需要 类似if(readableBytes() > 4)
这样的判断了,
ReplayingDecoder
内部会处理,使用起来十分方便,但它也是有一些局限性的,比如:
- 不是所有的
ByteBuf
操作都支持,若不支持,,将抛出异常 ReplayingDecoder
在某些情况下性能比不过ByteToMessageDecoder
,比如网络慢且消费格式复杂时,消息会被拆成很多碎片,处理起来慢很多。
五、其他 codec
LineBasedFrameDecoder
--> 使用 行尾控制字符\r\n
等来解析数据,在netty 部分类中也有使用DelimiterBasedFrameDecoder
--> 使用自定义的字符作为消息的分隔符HttpObjectDecoder
–> 一个HTTP的解码器LengthFieldBasedFrameDecoder
--> 通过长度来标识整包,这样就可以自动处理半包和粘包问题了。