经过上一篇的分析,我已经对ntty的服务端的启动流程以及客户端连接之后的数据发送逻辑有了一定的认识。
**以下是channel注册到workerGroup的流程**
- bossGroup在接收到客户端连接发送数据的请求之后,会将这个channel注册到workerGroup上。
- workerGroup收到注册请求之后,执行ChannelIntializer的initChannel方法,将我们自己的handler加入到pipeline中
- handler加入到pipeline的handler联之后,依次执行每一个handler的channelRegistered方法
- 接着执行handler的channelActive方法
- 最后执行read方法。这个read方法是从handler的tail开始往前推,并且只执行outboundHandler(暂时不知道这个的用处)
注册到workerGroup上之后,他会有一个异步线程去自旋,处理管理的通道的读写事件
假如客户端发送了数据过来
- 获取发生事件的channel(在select那个switch中就会拿到这个channel)
- 进行读取数据(从handler的head开始处理-----这一块都是调用的inBoundHandler入栈)
- 循环多次将数据读取到buffer中(PooledUnsafeDirectByteBuf)直接内存了。
- 调用handler的channelRead去处理读事件(一般在这里面会涉及到数据的解码)
- 比如ByteToMessageDecoder就是在这一块调用内部方法callDecode
- 当调用一次解码之后,会去调用下一个handler来处理解码之后的数据
- 之后再去调用readComplete方法。到了这里,差不多数据也就被我们服务段处理完成了
再来看看服务端给客户端发数据的流程
- handler调用ctx.writeAndFlush(msg) 将数据发送给客户端
- 调用pre获取上一个handler进行outBound的write操作(如果我们编码是在这个hander后面,那么就不会生效!)
- 比如MessageToByteEncoder就是贼这一块调用encode方法,对我们发送的数据进行加密
- 之后再调用preHandler进行数据处理
- 之后调用Head的flush方法里面会将数据写回到nio的那个socketChannel
- 最终会使用Head里面的unsafe.write(msg, promise)进行数据写会操作(其实是在Head的flush()方法中,会调用channel.write(buffer)将信息写会到channel中去)