1. 程式人生 > >七、Nio之SocketChannel

七、Nio之SocketChannel

Java NIO中的SocketChannel是一個連線到TCP網路套接字的通道。 可以通過以下2種方式建立SocketChannel: 1. 開啟一個 SocketChannel 並連線到網際網路上的某臺伺服器。 2. 一個新連線到達 ServerSocketChannel 時,會建立一個 SocketChannel。 開啟 SocketChannel 下面是 SocketChannel 的開啟方式:
  1. SocketChannel socketChannel =SocketChannel.open();
  2. socketChannel.connect(newInetSocketAddress("127.0.0.1",80));
關閉 SocketChannel 當用完 SocketChannel 之後呼叫 SocketChannel.close()關閉 SocketChannel:
  1. socketChannel.close();
從 SocketChannel  讀取資料 要從 SocketChannel 中讀取資料,呼叫一個 read()的方法之一。以下是例子:
  1. ByteBuffer
    buf =ByteBuffer.allocate(48);
  2. int bytesRead = socketChannel.read(buf);
首先,分配一個 Buffer。從 SocketChannel 讀取到的資料將會放到這個 Buffer 中。 然後,呼叫 SocketChannel.read()。該方法將資料從 SocketChannel 讀到 Buffer 中。read()方法返回的 int 值表示 讀了多少位元組進 Buffer 裡。如果返回的是-1,表示已經讀到了流的末尾(連線關閉了)。 寫入 SocketChannel 寫資料到 SocketChannel 用的是 SocketChannel.write()方法,該方法以一個 Buffer 作為引數。示例如下:
  1. String
    newData ="New String to write to file..."+System.currentTimeMillis();
  2. ByteBuffer buf =ByteBuffer.allocate(48);
  3. buf.clear();
  4. buf.put(newData.getBytes());
  5. buf.flip();
  6. while(buf.hasRemaining()){
  7.    channel.write(buf);
  8. }
注意 SocketChannel.write()方法的呼叫是在一個 while 迴圈中的。Write()方法無法保證能寫多少位元組到SocketChannel。所以,我們重複呼叫 write()直到 Buffer 沒有要寫的位元組為止。
非阻塞模式 可以設定 SocketChannel 為非阻塞模式(non-blocking mode).設定之後,就可以在非同步模式下呼叫 connect(),read() 和write()了。 connect() 如果 SocketChannel 在非阻塞模式下,此時呼叫 connect(),該方法可能在連線建立之前就返回了。為了確定連線 是否建立,可以呼叫 finishConnect()的方法。像這樣:
  1. socketChannel.configureBlocking(false);
  2. socketChannel.connect(newInetSocketAddress("127.0.0.1",80));
  3. while(! socketChannel.finishConnect()){
  4. //wait, or do something else...
  5. }
write() 非阻塞模式下,write()方法在尚未寫出任何內容時可能就返回了。所以需要在迴圈中呼叫 write()。前面已經有例子 了,這裡就不贅述了。 read() 非阻塞模式下,read()方法在尚未讀取到任何資料時可能就返回了。所以需要關注它的 int 返回值,它會告訴你讀取 了多少位元組。 非阻塞模式與選擇器 非阻塞模式與選擇器搭配會工作的更好,通過將一或多個 SocketChannel 註冊到 Selector,可以詢問選擇器哪個通 道已經準備好了讀取,寫入等。Selector 與 SocketChannel 的搭配使用會在後面詳講。