#三更半页 数据是如何进行传输的?看看网络传输层的抽象。 区别于client端和server端。当建立连接时, client端创建的是阻塞式的BioWritableChannel; server端创建的是非阻塞式的NioWritableChannel。先看简单的client端的处理—— client端的WritableChannel创建时发送、读取都基于Soket对象的input流和output流。 read方法需要实现,接受一个连接对象,主要用例handle网络对象(NetBuffer); wirte方法接受的对象也是NetBuffer client端发送数据:send方法(构造并添加回调函数,这个回调会在收到response时被调用) 第一:构造输出流 TransferOutputStream ,这里的out对象是DataOutputStream,底层的outstream流是自定义的ResettableBufferOutputStream,这里维护了NetBuffer的对象buffer,其中又包含了DataBuffer对象,后者是最终利用ByteBuffer来管理数据的写入和读取。所以层次结构如下—— TransferOutputStream (l.net) -->DataOutputStream(resettableOutputStream) (java.io) ---->NetBufferOutputStream (l.net) ------> NetBuffer (l.net) -------->DataBuffer (l.common) ---------->ByteBuffer (java.nio) 第二:对数据包进行编码。包含 header 和 data 数据。(不同协议包进行不同的encode) 第三:利用TransferOutputStream flush方法发送数据: writePacketLength(); // 写如包大小 int值 buffer.flip(); // 翻转buffer,从写入模式进入读取模式 writableChannel.write(buffer); // 准备发送 第四:利用TansferConnection中的WritableChannel里的socket对象进行发送 client端是阻塞模式,所有直接从通道中准备读取数据—— tcpConnection.getWritableChannel().read(tcpConnection); 包括以下几步: 第一:读取长度, 第二:根据长度,构造DataBuffer对象并设置limit大小 第三:获取byteBuffer,从socket中读取指定大小数据 第四:构造NetBuffer对象 第五:处理对象 conn.handle(netBuffer); handle的实现都是在TansferConnection中,但对应client来说这里是收到了server端的响应,handleResponse即可(在TcpClientConnection中重写处理;对应的handleRequest 在TcpServerConnection中处理) TransferInputStream对象也是基于NetBuffer来构造的 ,并且实现了NetInputStream接口 new DataInputStream(new NetBufferInputStream(inBuffer)); 处理逻辑: 第一:确保返回的status正确 第二:没有异常信息 第三:根据packetId获取回调函数(必须有回调,在执行send方法发送前会构造并添加这个回调函数到clientConnection中) 回调本身定义了run方法;调用runInternal(NetInputStream in) 方法,然后在回调中重写,实际执行的是 // this is an AsyncCallback handleAsyncCallback(in, packet.getAckType(), ackPacketHandler, this); 最终在这个方法中根据packet类型获取解码器,对数据进行解码(每个协议包都有一个对应的解码器,在应用启动时就完成了注册) 这样完成第一次协议包的交互:SessionInit 和 SessionInitAct,最终创建完成了ClientSession。 https://asia.feed.base.one/posts/de2a73e4-d2e1-489f-a334-e2e077b2f1c5