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緩衝區。

相關文章
相關標籤/搜索