在NIO中有幾個核心對象需要掌握:緩衝區(Buffer)、通道(Channel)、選擇器(Selector)。
緩衝區Buffer
緩衝區實際上是一個容器對象,更直接的說,其實就是一個數組,在NIO庫中,所有數據都是用緩衝區處理的。在讀取數據時,它是直接讀到緩衝區中的; 在寫入數據時,它也是寫入到緩衝區中的;任何時候訪問 NIO 中的數據,都是將它放到緩衝區中。而在面向流I/O系統中,所有數據都是直接寫入或者直接將數據讀取到Stream對象中。
首先建立服務器端,代碼如下
<span style="font-size:14px;"> </span><span style="font-size:18px;">ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
ServerSocket serverSocket = serverSocketChannel.socket();
serverSocket.bind(new InetSocketAddress(port));
selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("server start on port:" + port);</span>
先建立通道,然後得到一個ServerSocket並綁定到一個端口上,Selector selector,這個就是nio中的選擇器,
<span style="font-size:18px;">serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);</span>
這句話的意思就是在我們的通道上註冊選取器選擇可接受的請求(SelectionKey.OP_ACCEPT)
我們還需要一個方法去輪詢我們的請求
<span style="font-size:18px;">while (true) {
try {
int readyChannels = selector.select();
if(readyChannels == 0) continue;
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {
if(key.isValid())
handle(key);
keys.remove(key);
};
} catch (Exception e) {
e.printStackTrace();
break;
}
</span><span style="font-size:14px;">
}</span>
首先選擇器去找到所有的請求,我們通過SelectionKey可以去處理這些請求
我們如何處理呢??
private void handle(SelectionKey selectionKey) throws Exception {
ServerSocketChannel server = null;
SocketChannel client = null;
if (selectionKey.isAcceptable()) {
server = (ServerSocketChannel) selectionKey.channel();
client = server.accept();
client.configureBlocking(false);
client.register(selector, SelectionKey.OP_READ);
} else if (selectionKey.isReadable()) {
client = (SocketChannel) selectionKey.channel();
if (client.isConnected()) {
try {
rBuffer.clear();
while (client.read(rBuffer) > 0) {
rBuffer.flip();
}
byte[] save = rBuffer.array();
ByteArrayInputStream bi = new ByteArrayInputStream(save);
ObjectInputStream oi = new ObjectInputStream(bi);
bi.close();
oi.close();
if (client.isConnected()) {
client.register(selector, SelectionKey.OP_READ);
} else {
System.out.println("2連接斷開aaaaaa");
}
} catch (IOException e) {
client.close();
System.out.println("2異常無連接aaaaaa");
}
} else {
System.out.println("連接斷開=======");
}
}
}
讀數據需要單獨的線程,如:
while (true) {
while (scanner.hasNext()) {
mess = scanner.next();
try {
server.server_fasong(mess);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
ok啦,這樣既可以讀又可以寫啦