关于netty:Netty-草稿

Reactor开发模式
SocketChannel 在client端监听op_connect,op_write,op_read事件,在server只监听op_write,op_read事件,ServerSocketChannel在server端运行,只监听op_accept事件

netty对Reactor模式的实现
首先ServerSocketChannel是能够创立子的socketchannel,创立是由
BootstrapChannelFactory这个工厂类依据传入的class反射来创立,
所以
serverBootstrap.group().channel(xxx.class) .channel这个时候就是由下面的工厂类利用反射动静的创立一个channel,绑定在对应的group上

serverBootstrap.group(bossGroup,workerGroup) .channel传进来的会创立一个channel绑定在bossGroup上,而后传进来的ServerSocketChannel能够创立子socketchannel绑定在wokergroup上

再和下面的reactor开发模式对应,就是serversocketchannel绑定在bossGroup上来负责监听op_accept事件,socketchannel绑定在workergroup上来负责监听其余read write事件

粘包和半包

TCP为什么会呈现粘包和半包(UDP其实没有这个问题):次要是因为TCP是流协定

罕用的解决这种问题的计划:要么短链接,要么长链接中采纳封装成桢framing技术

netty对应用Framing粘包半包的反对:
固定长度的形式:肯定就按固定长度的来传,不够就补空,解码FixedLengthFrameDecoder
宰割符的形式:以指定的宰割符来宰割,但要思考内容中如果有这个宰割符须要本义,解码DelimiterBasedFrameDecoder
固定长度字段存内容的长度信息:要思考预留多少位来存储这个长度,解码器是LengthFieldBasedFramedDecoder,编码器LengthFieldPrepender

下面的编码器都继承了ByteToMessageDecoder这个抽象类

ByteToMessageDecoder 继承 ChannelInboundHandlerAdapter
ChannelInboundHandlerAdapter 中有一个channelRead办法解决数据,ByteToMessageDecoder 中就具体实现了channelRead办法
ByteToMessageDecoder中保护了一个ByteBuf类型的数据积攒器cumulation,如果是第一笔数据间接赋值给cumulation,不是第一笔的就追加在cumulation前面,而后调

  callDecode(ctx, cumulation, out);
  
  //其中callDecode中会调
  decodeRemovalReentryProtection(ctx, in, out);
  //而后这个又会调decode(ctx, in, out);//这个decode是ByteToMessageDecoder中提供的形象办法,具体由下面的各种Decoder来实现
  

以FixedLengthFrameDecoder为例子

public class FixedLengthFrameDecoder extends ByteToMessageDecoder {
    private final int frameLength;

    public FixedLengthFrameDecoder(int frameLength) {
        if(frameLength <= 0) {
            throw new IllegalArgumentException("frameLength must be a positive integer: " + frameLength);
        } else {
            this.frameLength = frameLength;
        }
    }

    protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        Object decoded = this.decode(ctx, in);
        if(decoded != null) {
            out.add(decoded);//每一次解进去的数据放在out中
        }

    }

    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        return in.readableBytes() < this.frameLength?null:in.readSlice(this.frameLength).retain();
        //如果以后积攒器就是这里的in中的数据小于定义的长度,不做任何操作,这个时候数据也不够,超过定义的长度,取frameLength长度的数据进去,剩下的就还在积攒器中
    }

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理