// 1. 打开ServerSocketChannel,用于监听客户端的连接
ServerSocketChannel open = ServerSocketChannel.open();
// 2. 绑定监听端口,设置连接为非阻塞模式
open.accept().bind(new InetSocketAddress(InetAddress.getByName("IP"), port));
open.configureBlocking(false);
// 3. 创建reactor线程,创建多路复用器并启动线程
Selector selector = Selector.open();
new Thread(new ReactorTask()).start();
// 4. 将ServerSocketChannel注册到Reactor线程的多路复用器Selector上,监听ACCEPT事件
SelectionKey key = open.register(selector, SelectionKey.OP_ACCEPT, ioHandler);
// 5. 多路复用器在线程run方法的无限循环体内轮询准备就绪的key
int num = selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> it = selectionKeys.iterator();
while (it.hasNext()){
SelectionKey next = it.next();
}
// 6. 多路复用监听到有新的客户端接入。处理新的接入请求,完成TCP三次握手,建立物理链路
SocketChannel channel = open.accept();
// 7. 设置客户端链路为非阻塞模式
channel.configureBlocking(false);
channel.socket().setReuseAddress(true);
// 8. 将新接入的客户端来你就饿注册到Reactor线程的多路复用器上,监听读操作,读取客户端发送的网络消息
SelectionKey key = socketChannel.register(selector, SelectionKey.OP_READ, ioHandler);
// 9. 异步读取客户端请求消息到缓冲区
int readNumber = channel.read(receivedBuffer);
// 10. 对ByteBuffer进行编解码,如果有半包消息指针reset,继续读取后续的报文,将解码成功的消息封装成Task,投递到业务线程池中,进行业务逻辑编排
Object message = null;
while (buffer.hasRemain()){
byteBuffer.mark();
Object message = decode(byteBuffer);
if (message == null){
ByteBuffer.reset();
break;
}
messageList.add(message);
}
if (!byteBuffer.hasRemain()){
byteBuffer.clear();
}else {
byteBuffer.compact();
}
if (messageList != null && !messageList.isEmpty()){
if (Object messageE : messageList){
handlerTask(messageE);
}
}
// 11. 将POJO对象encode成ByteBuffer,调用SocketChannel的异步write接口,将消息异步发送给客户端
socketChannel.write(buffer);
/**
* 如果发送区TCP缓冲区满,会导致写半包,此时,需要注册监听写操作位,
* 循环写,直到整包消息写入TCP缓冲区
*
*/
代码对应的时序图