NIO入门案例之分析NIO服务端序列图

        // 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缓冲区
         *
         */

代码对应的时序图

猜你喜欢

转载自blog.csdn.net/wildwolf_001/article/details/81069180