9 Java NIO SocketChannel-翻譯

王金龍發表於2017-12-05

Java NIO的SocketChannel是一個連線到TCP網路的Channel。建立ScoketChannel有兩種方式:

  1. 開啟一個SocketChannel,並且連線到網際網路上的某臺伺服器。
  2. 一個新連線到達ServerSocketChannel時,會建立SocketChannel。

Opening a SocketChannel

SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InnetSocketAddress("http://jenkov.com",80);
複製程式碼

Closing a SocketChannel

關閉SocketChannel可以通過SocketChannel.close()方法。如下所示。

socketChannel.close();
複製程式碼

Reading from a SocketChannel

可以通過read()方法來實現從SocketChannel中讀取資料。下面是一個例子:

ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf);
複製程式碼

首先,為一個Buffer分配空間,從SocketChannel中讀到的資料會寫入到這個Buffer中。

然後,呼叫SockedChannel的read()方法。這個方法會將SocketChannel中的資料寫入到Buffer中。read()方法的返回值表示寫入到Buffer中的位元組數。如果返回-1,說明已經到達流的末尾(連線已經關閉)。

Writing to a SocketChannel

可以通過SocketChannel.write()方法向SocketChannel寫入資料,這個方法將Buffer作為引數。下面是一個例子:

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);
}
複製程式碼

注意SocketChannel.write()方法的呼叫是在一個while迴圈中的。Write()方法無法保證能寫多少位元組到SocketChannel。所以,我們重複呼叫write()直到Buffer沒有要寫的位元組為止。

Non-blocking Mode

可以將SocketChannel設定為非阻塞模式。這樣做以後,connect(),read()和write()方法都將工作在非同步模式。

connect()

如果SocketChannel工作在非阻塞模式,那麼可以呼叫connect()方法,這個方法可能會在連線建立之前就返回。為了判斷連線是否已經建立了,可以通過呼叫finishConnect()方法,如下所示:

socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("http://jenkov.com",80);

while(! socketChannel.finishConnect()){
    // wait,or do something else ...
}
複製程式碼

write()

在非阻塞模式中,write()方法會在沒有寫任何資料之前就返回。因此,需要在迴圈中呼叫write()方法。但是,由於這個已經在前面的例子中講過了,這裡也沒有什麼需要進行特殊處理。

read()

在非阻塞模式中, read()方法會在沒有讀到任何資料之前立即返回。因此,需要關注方法的返回的整數值,它表明了已經讀到的位元組數。

Non-blocking Mode with Selectors

非阻塞模式與選擇器搭配會工作的更好,通過將一或多個SocketChannel註冊到Selector,可以詢問選擇器哪個通道已經準備好了讀取,寫入等。Selector與SocketChannel的搭配使用會在後面詳講。

相關文章