写节点
我们在 protocolwriternode
类中添加的两个核心方法 sendmsg()
,在发送消息时候参数有object代表的消息体以及writecallback
代表的消息回调函数,使用encoder
将其编码到writer buffer
中进行发送,
//调用接口函数
int r = protocol.onwrite(data, len);
//使用os的send函数进行发送
int t = os.send(scoket, data, len);
写出的字节数量与实际字节数量相同,那么就直接调用对应的回调函数。
if (r == len && writeCallback != null) {
writeCallback.invokeOnSuccess(channel);
}
写出的字节数为0,代表TCP连接处于不可写状态,此时我们应该从Writer线程注册一个多路复用的可写事件,在Poller线程检测到可写事件触发后,通知Writer重新发送消息,在这个TCP连接不可写的时间段内,我们应该把消息体和回调暂存在内存中。
//创建一个队列
queue = new ArrayQueue<>;
//拷贝一部分数据
copy(data, callback);
//等待重新发送数据
if(r < 0) {
handleEvent(r);
}
写出的字节数在0与消息体大小之间,代表消息发送了一部分,在这种状态下我们应该不断进行重试,直到检测到消息发送完全,或是TCP连接不可写为止。
if (r > 0 && r < len) {
len = len - r;
data = data.asSlice(r, len);
} else {
break;
}
读节点
在读取数据的时候,我们使用是protocolPollerNode
这个节点,我们这个节点是与我们的channel进行深度绑定的,所以我们会对我们读到的数据进行编码:
//首先读取对应的数据
protocol.onread();
//处理数据
process();
但是我们也需要注意一点的是,我们读到的数据也很有可能不是完整的, 所以我们需要先对数据进行一次的备份处理:
if (readIndex >= 0 && readIndex < len) {
//主要使用了一个备份数组
tempBuffer = WriteBuffer.newDefaultWriteBuffer(Arena.ofConfined(), len);
tempBuffer.writeSegment(readIndex == 0 ? memorySegment :
memorySegment.asSlice(readIndex, len - readIndex));
}
当下次读取到完整的数据之后,我们将原来的数据进行一次拼接:
tempBuffer.writeSegment(memorySegment);
long len = tempBuffer.writeIndex();
long readIndex = process(tempBuffer.toSegment());
if (readIndex == len) {
tempBuffer.close();
tempBuffer = null;
} else if (readIndex > 0) {
tempBuffer = tempBuffer.truncate(readIndex);
}