傳統的BIO(blocking I/O)是阻塞的,伺服器端:ServerSocket負責綁定IP位址,啟動監聽端口,然後一直等待着用戶端連接配接,是阻塞的狀态;用戶端:Socket負責發起連接配接操作。連接配接成功後,讀和寫的操作同樣是等待阻塞的。經典模型是來一個用戶端,起一個線程,因為主線程要負責監聽,要重起一條線程處理用戶端請求。
NIO (non-blocking I/O)是同步非阻塞。打個比方,用戶端請求伺服器端建立連接配接,就好像伺服器端有很多個插孔,等着用戶端來插。NIO有一個大管家selecter一直在輪詢處理用戶端的連接配接和讀寫請求,先在那些插孔上放(register)一些key(對應程式設計api裡SelectionKey.OP_ACCEPT),看看有沒有人來連接配接,如果有則連接配接。連接配接之後再連接配接的通道上放上讀寫的key(下面的程式是SelectionKey.OP_READ)
package com.java.yan;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class NioSocketDemo {
private Selector selector;
public void initServer(int port) throws IOException{
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.socket().bind(new InetSocketAddress(port));
this.selector = Selector.open();
serverChannel.register(selector,SelectionKey.OP_ACCEPT);
System.out.println("伺服器已啟動。。。");
}
public void listenSelector() throws IOException{
while(true){
this.selector.select();
Iterator<SelectionKey> it = this.selector.selectedKeys().iterator();
while(it.hasNext()){
SelectionKey key = it.next();
it.remove();
handler(key);
}
}
}
private void handler(SelectionKey key) throws IOException {
if(key.isAcceptable()){
ServerSocketChannel serverchannel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = serverchannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
}else if(key.isReadable()){
SocketChannel socketChannel = (SocketChannel)key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int readData = socketChannel.read(buffer);
if(readData > 0){
String info = new String(buffer.array(),"GBK").trim();
System.out.println("服務端收到資料:"+info);
}else{
System.out.println("用戶端關閉。。。。");
key.cancel();
}
}
}
public static void main(String[] args) throws IOException {
NioSocketDemo niodemo = new NioSocketDemo();
niodemo.initServer(8888);
niodemo.listenSelector();
}
}
上面的是單線程模式的NIO,還有更新版的,一個selector負責輪詢,但是隻處理用戶端連接配接,連接配接成功會有對應線程處理讀寫工作,引入線程池。
AIO(Asynchronous I/O) 是異步非阻塞,先前是selector主動輪詢,現在換成用戶端的I/O請求都是由OS先完成了再通知伺服器應用去啟動線程進行處理。
等待完善。。。。。。。