NIO服務(wù)端通信序列圖如下:

下面,我們對NIO服務(wù)端的主要創(chuàng)建過程進(jìn)行講解和說明:
步驟一:打開ServerSocketChannel,用于監(jiān)聽客戶端的連接,它是所有客戶端連接的父管道,代碼示例如下:
ServerSocketChannel acceptorSvr = ServerSocketChannel.open();
步驟二:綁定監(jiān)聽端口,設(shè)置連接為非阻塞模式,示例代碼如下:
acceptorSvr.socket().bind(new InetSocketAddress(InetAddress.getByName("IP"),port));
acceptorSvr.configureBlocking(false);
步驟三:創(chuàng)建Reactor線程,創(chuàng)建多路復(fù)用器并啟動線程,代碼如下:
Selector selector = Selector.open();
New Thread(new ReactorTask()).start();
步驟四:將ServerSocketChannel注冊到Reactor線程的多路復(fù)用器Selector上,監(jiān)聽ACCEPT事件,代碼如下:
SelectionKey key = acceptorSvr.register(selector,SelectionKey.OP_ACCEPT,ioHandler);
步驟五:多路復(fù)用器在線程run方法的無限循環(huán)體內(nèi)輪詢準(zhǔn)備就緒的Key,代碼如下:
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 ...
}
步驟六:多路復(fù)用器監(jiān)聽到有新的客戶端接入,處理新的接入請求,完成TCP三次握手,建立物理鏈路,代碼示例如下:
SocketChannel channel = svrChannel.accept();
步驟七:設(shè)置客戶端鏈路為非阻塞模式,示例代碼如下:
channel.configureBlocking(false);
channel.socket().setReuseAddress(true);
......
步驟八:將新接入的客戶端連接注冊到Reactor線程的多路復(fù)用器上,監(jiān)聽讀操作,用來讀取客戶端發(fā)送的網(wǎng)絡(luò)消息,代碼如下:
SelectionKey key = socketChannel.register(selector,SelectionKey.OP_READ);
步驟九:異步讀取客戶端請求消息到緩沖區(qū),示例代碼如下:
int readNumber = channel.read(recelvedBuffer);
步驟十:對ByteBuffer進(jìn)行編解碼,如果有半包消息指針reset,繼續(xù)讀取后續(xù)的報文,將解碼成功的消息封裝成Task,投遞到業(yè)務(wù)線程池中,進(jìn)行業(yè)務(wù)邏輯編排,示例代碼如下:
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,調(diào)用SocketChannel的異步write方法,將消息異步發(fā)送給客戶端,示例代碼如下:
socketChannel.write(buffer);
注意:如果發(fā)送區(qū)TCP緩沖區(qū)滿,會導(dǎo)致寫半包,此時,需要注冊監(jiān)聽寫操作位,循環(huán)寫,直到整包消息寫入TCP緩沖區(qū)。