乐趣区

关于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 长度的数据进去,剩下的就还在积攒器中
    }
退出移动版