1. 程式人生 > >Java NIO框架Netty教程(六)

Java NIO框架Netty教程(六)

看到標題,您可能覺得,這跟Netty有什麼關係呢?確實,如果你完全是使用Netty的,那麼可能你可以完全不需要了解Selector。但是,不得不提的是,Netty底層關於NIO的實現也是基於Java的Selector的,是對Selector的封裝。所以,我個人認為理解好Selector對於使用和理解Netty都是很多有幫助的。當然,如果您確實不關心這些,只想會用Netty就可以了。那麼下文,您可以略過:)

我對於Selector也是新上手學習的。之前很多新人跟我交流,都會提到一個新框架或者一個新開源工具的使用和上手的問題。他們會覺得上手困難,耗費事件。不過筆者,從來沒有此種感覺。這裡正好,借用Selector

的學習過程,跟大家交流一下,我上手的過程。

想要使用一個工具,自然是先了解其定位,解決問題的原理或者工作流程。所以,筆者先從網上了解了一下Selector大概的工作流程。

NIO 有一個主要的類Selector,這個類似一個觀察者,只要我們把需要探知的socketchannel告訴Selector,我們接著做別的事情,當有事件發生時,他會通知我們,傳回一組SelectionKey,我們讀取這些Key,就會獲得我們剛剛註冊過的socketchannel,然後,我們從這個Channel中讀取資料,放心,包準能夠讀到,接著我們可以處理這些資料。

上面那段文字是我摘錄的一小段總結,就這一小段基本已經可以說明問題了。接下來,我們要考慮的就是,要實現這個過程,我們需要做什麼?順著描述,我們可以想象,需要選擇器,需要訊息傳送的通道,需要註冊一個事件,用於識別。通道自然需要繫結到一個地址。有了這樣大概的想法,我們就可以去API裡找相關的介面。

Selector服務端樣例程式碼:

/**
 * Java NIO Select模式服務端樣例程式碼
 * 
 * @author lihzh
 * @alia OneCoder
 * @Blog http://www.coderli.com
 * @date 2012-7-16 下午9:22:53
 */
public class NioSelectorServer {

	/**
	 * @author lihzh
	 * @throws IOException
	 * @alia OneCoder
	 * @date 2012-7-16 下午9:22:53
	 */
	public static void
main(String[] args) throws IOException { // 建立一個selector選擇器 Selector selector = Selector.open(); // 開啟一個通道 ServerSocketChannel socketChannel = ServerSocketChannel.open(); // 繫結到9000埠 socketChannel.socket().bind(new InetSocketAddress(8000)); // 使設定non-blocking的方式。 socketChannel.configureBlocking(false); // 向Selector註冊Channel及我們有興趣的事件 socketChannel.register(selector, SelectionKey.OP_ACCEPT); for (;;) { // 選擇事件 selector.select(); // 當有客戶端準備連線到服務端時,便會出發請求 for (Iterator<SelectionKey> keyIter = selector.selectedKeys() .iterator(); keyIter.hasNext();) { SelectionKey key = keyIter.next(); keyIter.remove(); System.out.println(key.readyOps()); if (key.isAcceptable()) { System.out.println("Accept"); // 接受連線到此Channel的連線 socketChannel.accept(); } } } } }

Selector客戶端樣例程式碼:

/**
 * Java NIO Selector模式,客戶端程式碼
 * 
 * @author lihzh
 * @alia OneCoder
 * @blog http://www.coderli.com
 */
public class NioSelectorClient {

	/**
	 * @author lihzh
	 * @throws IOException 
	 * @alia OneCoder
	 */
	public static void main(String[] args) throws IOException {
		SocketChannel channel = SocketChannel.open();
		channel.configureBlocking(false);
		channel.connect(new InetSocketAddress("127.0.0.1", 8000));
	}
}

程式碼很簡單,服務端接受到客戶端的連線請求後,會打印出”Accept“資訊。

簡單概括就是,整一個通道,通道加個選擇過濾器,看來的事件是不是我想要的,不想要的乾脆不管,想要的,我就存起來,留著慢慢處理。

現在感覺是不是Netty確實跟這個機制比較像,如果讓你去實現Netty現有的功能,也有思路可想了吧。