天天看點

NIO程式設計

 傳統的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先完成了再通知伺服器應用去啟動線程進行處理。

等待完善。。。。。。。

繼續閱讀