2. Netty初认识--NIO入门---客户端处理概述

  |   0 评论   |   0 浏览

image.png

示例代码如下,以下相当于伪代码,不能运行

package club.wujingjian.com.wujingjian.nio;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class ClientPoint {

    public static void main(String[] args) throws IOException {
        //步骤一: 打开SocketChannel,绑定客户端本地地址(可选,默认系统会随机分配一个可用的本地地址),示例代码如下:
        SocketChannel clientChannel = SocketChannel.open();

        //步骤二: 设置SocketChannel为非阻塞模式,同时设置客户端连接的TCP参数,示例如下:
        clientChannel.configureBlocking(false);
        socket.setReuseAddress(true);
        socket.setReceiveBufferSize(BUFFER_SIZE);
        socket.setSendBufferSize(BUFFER_SIZE);

        //步骤三: 异步连接服务端,
        boolean connected = clientChannel.connect(new InetSocketAddress("ip",port));

        //步骤四:判断是否连接成功,如果连接成功,直接注册读状态位到多路复用器中,如果没有连接成功(异步连接,返回false,说明客户端已经发送sync包,服务端没有返回ack包,物理链路还没有建立)
        if (connected) {
            clientChannel.register(selector, SelectionKey.OP_READ, ioHandler);
        } else {
            clientChannel.register(selector, SelectionKey.OP_CONNECT, ioHandler);
        }

        //步骤五: 向Reactor线程的多路复用器注册OP_CONNECT状态位,监听服务端的TCP ACK应答,
        clientChannel.register(selector, SelectionKey.OP_CONNECT, ioHandler);

        //步骤六: 创建Reactor线程,创建多路复用器并启动线程
        Selector selector = Selector.open();
        new Thread(new ReactorTask()).start();

        //步骤七: 多路复用器在线程run方法的无限循环体内轮询准备就绪的key
        int num = selector.select();
        Set selectedKeys = selector.selectedKeys();
        Iterator it = selectedKeys.iterator();
        while (it.hasNext()) {
            SelectionKey key = (SelectionKey) it.next();
            // 处理IO 事件
        }

        //步骤八: 接收connect事件进行处理
        if (key.isConnectable()) {
            //处理连接操作
        }

        //步骤九:判断连接结果,如果连接成功,注册读事件到多路复用器,
        if (clientChannel.finishConnect()) {
            registerRead();
        }

        //步骤十:注册读事件到多路复用器
        clientChannel.register(selector,SelectionKey.OP_READ, ioHandler);

        //步骤十一:异步读客户端请求消息到缓冲区
        int readNumber = channel.read(receivedBuffer);

        //步骤十二:对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()) {
            for (Object messageE : messageList) {
                handlerTask(messgaeE);
            }
        }

        //步骤十三:将POJO对象encode成ByteBuffer,调用SocketChannel的异步write接口,将消息异步发送给客户端
        socketChannel.write(buffer);
    }
}


标题:2. Netty初认识--NIO入门---客户端处理概述
作者:码农路上
地址:http://wujingjian.club/articles/2020/02/27/1582775817440.html