一、ServerSocketChannel Java NIO中的 ServerSocketChannel 是一個可以監聽新進來的TCP連接的通道, 就像標準IO中的ServerSocket一樣。ServerSocketChannel類在 java.nio.channels包中。 打開 ServerS ...
一、ServerSocketChannel
Java NIO中的 ServerSocketChannel 是一個可以監聽新進來的TCP連接的通道, 就像標準IO中的ServerSocket一樣。ServerSocketChannel類在 java.nio.channels包中。
打開 ServerSocketChannel
通過調用 ServerSocketChannel.open() 方法來打開ServerSocketChannel.
關閉 ServerSocketChannel
通過調用ServerSocketChannel.close() 方法來關閉ServerSocketChannel.
監聽新進來的連接
通過 ServerSocketChannel.accept() 方法監聽新進來的連接。當 accept()方法返回的時候,它返回一個包含新進來的連接的 SocketChannel。因此, accept()方法會一直阻塞到有新連接到達。
通常不會僅僅只監聽一個連接,在while迴圈中調用 accept()方法.
當然,也可以在while迴圈中使用除了true以外的其它退出準則。
非阻塞模式
ServerSocketChannel可以設置成非阻塞模式。在非阻塞模式下,accept() 方法會立刻返回,如果還沒有新進來的連接,返回的將是null。 因此,需要檢查返回的SocketChannel是否是null.如:
/** * socket server channel */ @Test public void text2() throws IOException { ServerSocketChannel channel = ServerSocketChannel.open(); //新建channel channel.socket().bind(new InetSocketAddress(9999)); //監聽埠 channel.configureBlocking(true); //設置阻塞 while (true) { SocketChannel accept = channel.accept(); //設置為阻塞,則此方法阻塞,直到有連接 //如果設置為非阻塞,需要在這裡判斷 accept == null? ByteBuffer byteBuffer = ByteBuffer.allocate(1024); accept.read(byteBuffer); byteBuffer.flip(); //反轉 while (byteBuffer.hasRemaining()) { //判斷 System.err.println((char)byteBuffer.get()); //輸出 } } }
二、SocketChannel
Java NIO中的SocketChannel是一個連接到TCP網路套接字的通道。可以通過以下2種方式創建SocketChannel:
- 打開一個SocketChannel並連接到互聯網上的某台伺服器。
- 一個新連接到達ServerSocketChannel時,會創建一個SocketChannel。
打開 SocketChannel
下麵是SocketChannel的打開方式:
關閉 SocketChannel
當用完SocketChannel之後調用SocketChannel.close()關閉SocketChannel:
從 SocketChannel 讀取數據
要從SocketChannel中讀取數據,調用一個read()的方法之一。
首先,分配一個Buffer。從SocketChannel讀取到的數據將會放到這個Buffer中。
然後,調用SocketChannel.read()。該方法將數據從SocketChannel 讀到Buffer中。read()方法返回的int值表示讀了多少位元組進Buffer里。如果返回的是-1,表示已經讀到了流的末尾(連接關閉了)。
寫入 SocketChannel
寫數據到SocketChannel用的是SocketChannel.write()方法,該方法以一個Buffer作為參數。
註意SocketChannel.write()方法的調用是在一個while迴圈中的。Write()方法無法保證能寫多少位元組到SocketChannel。所以,我們重覆調用write()直到Buffer沒有要寫的位元組為止。
非阻塞模式
可以設置 SocketChannel 為非阻塞模式(non-blocking mode).設置之後,就可以在非同步模式下調用connect(), read() 和write()了。
connect()
如果SocketChannel在非阻塞模式下,此時調用connect(),該方法可能在連接建立之前就返回了。為了確定連接是否建立,可以調用finishConnect()的方法。
write()
非阻塞模式下,write()方法在尚未寫出任何內容時可能就返回了。所以需要在迴圈中調用write()。前面已經有例子了,這裡就不贅述了。
read()
非阻塞模式下,read()方法在尚未讀取到任何數據時可能就返回了。所以需要關註它的int返回值,它會告訴你讀取了多少位元組。
非阻塞模式與選擇器
非阻塞模式與選擇器搭配會工作的更好,通過將一或多個SocketChannel註冊到Selector,可以詢問選擇器哪個通道已經準備好了讀取,寫入等。Selector與SocketChannel的搭配使用會在後面詳講。
/** * socket channel */ @Test public void test3() throws IOException { SocketChannel channel = SocketChannel.open(); //新建服務端 channel.connect(new InetSocketAddress("127.0.0.1",9999)); //連接服務端地址 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); //緩衝區 byteBuffer.put("123".getBytes()); byteBuffer.flip(); //反轉 while (byteBuffer.hasRemaining()) { //判斷 channel.write(byteBuffer); } }