NIO入门之NIO编程「NIO服务端序列图」

NIO服务端通讯序列图以下:java

下面,咱们对NIO服务端的主要建立过程进行讲解和说明:网络

步骤一:打开ServerSocketChannel,用于监听客户端的链接,它是全部客户端链接的父管道,代码示例以下:异步

ServerSocketChannel acceptorSvr = ServerSocketChannel.open();

步骤二:绑定监听端口,设置链接为非阻塞模式,示例代码以下:socket

acceptorSvr.socket().bind(new InetSocketAddress(InetAddress.getByName("IP"),port));
acceptorSvr.configureBlocking(false);

步骤三:建立Reactor线程,建立多路复用器并启动线程,代码以下:线程

Selector selector = Selector.open();
New Thread(new ReactorTask()).start();

步骤四:将ServerSocketChannel注册到Reactor线程的多路复用器Selector上,监听ACCEPT事件,代码以下:指针

SelectionKey key = acceptorSvr.register(selector,SelectionKey.OP_ACCEPT,ioHandler);

步骤五:多路复用器在线程run方法的无限循环体内轮询准备就绪的Key,代码以下:code

int num = selector.select();
Set selectedKey s = selector.selectedKeys();
Iterator it = selectedKeys.iterator();
while(it.hasNext()){
    SelectionKey key = (SelectionKey)it.next();
    // ... deal with I/O event ...
}

步骤六:多路复用器监听到有新的客户端接入,处理新的接入请求,完成TCP三次握手,创建物理链路,代码示例以下:对象

SocketChannel channel = svrChannel.accept();

步骤七:设置客户端链路为非阻塞模式,示例代码以下:事件

channel.configureBlocking(false);
channel.socket().setReuseAddress(true);
......

步骤八:将新接入的客户端链接注册到Reactor线程的多路复用器上,监听读操做,用来读取客户端发送的网络消息,代码以下:get

SelectionKey  key = socketChannel.register(selector,SelectionKey.OP_READ);

步骤九:异步读取客户端请求消息到缓冲区,示例代码以下:

int readNumber = channel.read(recelvedBuffer);

步骤十:对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(messageE);
}

步骤十一:将POJO对象encode成ByteBuffer,调用SocketChannel的异步write方法,将消息异步发送给客户端,示例代码以下:

socketChannel.write(buffer);

注意:若是发送区TCP缓冲区满,会致使写半包,此时,须要注册监听写操做位,循环写,直到整包消息写入TCP缓冲区。

相关文章
相关标签/搜索