NIO客戶端主要建立過程

NIO客戶端主要建立過程:
 
步驟一:打開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(seletor,SelectionKey.OP_READ,ioHandler);
}else{
     clientChannel.register(selector,Selection.OP_CONNECT,ioHandler);
}

步驟五:向Reactor線程的多路複用器註冊OP_CONNET狀態位,監聽服務端的TCP ACK應答,示例代碼以下:java

 clientChannel.register(select, 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();
     //...deal with  I/O event ...
}
 
步驟八:接收connect事件進行處理,示例代碼以下:
 
if(key.isConnectable()){
     //handlerConnect();
}

步驟九:判斷鏈接成功,若是鏈接成功,註冊讀事件到多路複用器,示例代碼以下: socket

if(channel.finishConnect()){
     registerRead();
}
 
步驟十:註冊讀事件到多路複用器,示例代碼以下:
 
clientChannel.register(selector,SelectionKey.OP_READ,ioHandler);

步驟十一:異步讀客戶端請求消息到緩衝區,示例代碼以下: 線程

int readNumber = channel.read(receivedBuffer);

步驟十二:對ByteBuffer進行編解碼,若是有半包消息接收緩衝區Reset,繼續讀取後續的報文,將解碼成功的消息封裝成Task,投遞到業務線程池中,進行業務邏輯編排,示例代碼以下: code

Object message = null;
whiel(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);
相關文章
相關標籤/搜索