NIO——SocketChannel

 SocketChannel 是連接到 TCP 網絡套接字的 Channel,相當於 Java 網絡編程中的 Socket。有兩種創建 SocketChannel 的方式:

  • 手動開啓一個 SocketChannel 並連接到因特網上的一個服務器
  • 當傳入的連接到達 ServerSocketChannel 時或者說 ServerSocketChannel 新進來一個連接的時候會創建一個 SocketChannel

 1、開啓一個 SocketChannel
 示例如下:

SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));

 2、關閉一個 SocketChannel
 通過調用 SocketChannel 的 close() 方法可以關閉這個 SocketChannel:

socketChannel.close(); 

 3、從 SocketChannel 中讀取數據
 可以通過調用 SocketChannel 的 read() 或其重載方法讀取 SocketChannel 中的數據:

ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = socketChannel.read(buf);

 首先分配一個 Buffer,數據從 SocketChannel 中讀取後寫入該 Buffer。然後調用 SocketChannel.read() 方法達到上述目的,該方法的返回值顯示了向指定的 Buffer 中寫入了多少個字節的數據,如果返回 -1 表示數據讀取結束(連接被關閉)。
 4、向 SocketChannel 中寫數據
 調用 SocketChannel 的 write() 方法可以向 SocketChannel 中寫數據,需要傳入一個 Buffer,表示將該 Buffer 中的數據寫入到 SocketChannel 中:

String newData = "New String to write to file..." + System.currentTimeMillis();

ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());

buf.flip();//從頭開始寫入

while(buf.hasRemaining()) {
    channel.write(buf);//將Buffer中的數據寫入到SocketChannel中
}

 注意把 SocketChannel.write() 方法的調用放在一個 while 循環中。由於無法保證有多少字節會寫入到 SocketChannel 中,因此需要重複調用 write() 方法直到沒有數據可以寫爲止。
 5、非阻塞模式
 可以將 SocketChannel 設置爲非阻塞的。這樣的話,就可以使 connect()、read()、write() 這些方法異步執行。
 ①connect()
 如果 SocketChannel 設置爲了非阻塞的,在調用 connect() 方法的時候,這個方法可能會在連接建立之前返回。要確定連接是否已經建立,可以調用 finishConnect() 方法,示例如下:

socketChannel.configureBlocking(false);//將SocketChannel設置爲非阻塞的
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));//建立連接(異步)

while(!socketChannel.finishConnect() ){//若連接尚未創建
    //等待,或者執行別的操作   
}

 ②write()
 非阻塞模式下 write() 方法可能在還沒有寫入任何數據時返回。因此需要在一個循環中調用 write(),我們前面的示例中一直是這麼做的,因此對於 write() 來說不需要做什麼改動。
 ③read()
 在非阻塞模式下 read() 方法可能會在還沒有讀取任何數據的情況下返回。因此需要關注該方法的返回值,該返回值表明了讀取了多少字節的數據。
 ④非阻塞模式下的 Selector
 非阻塞模式的 SocketChannel 和 Selector 搭配更好,將一個或多個 SocketChannel 註冊到一個 Selector 中,然後通過輪詢這個 Selector 察看是否有準備好讀寫的 Channel,至於 Selector 和 SocketChannel 怎麼搭配使用後面會有詳細的講述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章