接上一講對mina的簡單應用和對mina服務端和客戶端中幾個重要的技術知識點的理解后,今天着重對mina服務端的NioSocketAcceptor 進行學習。
說這個玩意之前,先整體上看一下在mina框架中NioSocketAcceptor和NioSocketConnector 這兩個玩意的整體代碼結構:
從上面的代碼結構我做如下的解釋:
服務端通過創建一個NioSocketAcceptor來接受請求,客戶端通過創建NioSocketConnector來連接服務端並發送請求。
IoService是對於服務器端接受連接和客戶端發起連接兩類行為的一個抽象。IoServer用來執行真正的 I/O 操作,以及管理 I/O 會話。兩個子接口為IoAcceptor和IoConnector。IoAcceptor用來接受連接,與客戶端進行通訊。IoConnector用來發起連接,與服務端進行通訊。IoAcceptor和IoConnector都分別有基於TCP/IP協議協議,UDP/IP協議以及虛擬機管道通訊的子接口。
上面是NioSocketAcceptor和NioSocketConnector的一個類的結構,現在我們從服務端先來說:先看一下服務端的代碼繼承和接口:
在這里我們知道我們想使用mina的時候就是先從一個NioSocketAcceptor定義開始,定義NioSocketAcceptor的時候需要綁定或者指定其對應的過濾器,IOHandler處理器,線程池等等。從源碼中我們可以知道NioSocketAcceptor的方法的入口是linstener,結束的出口是dispose()。哪我們就從一個NioSocketAcceptor的定義開始。
首先看一下我們定義開始的地方跟我們上一講中實現一個mina服務端編寫是一樣的。在這里我們重點來看我們實現了一個MinaSocketServer的接口,而這個接口中只有兩個方法
我們從listener的方法中可以看到是這樣的實現,定義一個NioSocketAcceptor,指定過濾鏈,iohandler處理器,綁定端口。我們就先從初始化的NioSocketAcceptor來說,先看NioSocketAcceptor的new操作》
我們可以看到對NioSocketAcceptor的初始化創建的時候是傳入了一個SimpleIoProcessorPool對象,而其中有NioProcessor和一個線程池,對這兩個的解釋我們先放到后面,先來看nioSocketAcceptor的構造函數源碼:
在這個代碼中我們需要注意一下哈 這里的這個selector是用volatile來修飾的,這樣在線程每次使用的時候,都會讀取變量修改后的最的值。想想這是為什么。或者在面試的時候人家問你在什么地方見到過這個詞,知道了吧,這就是我們讀源碼的好處,到時候說不上你的面試官都不知道^_^
在這里我們只是看到的nioSocketAcceptor的實現:下面是父類的實現以及解釋:
而在子類的init實現方法中我們可以看到做了如下的操作:
也就是打開一個選擇器,說到這里我們想大家應該有點印象了,因為在我們之前將nio的時候我們知道在NIO中就是這個Secletor對管道進行管理的,也就是這個selector是一個類似於服務端和客戶端管道大管家的角色,在這個secletor上注冊了不同的事件,來相應。那么在這里我們知道是打開了這個secletor。哪可能你會問,哪我到這里換沒有看到你的管道channel,selector等等的創建啊,好,其實我也是這么想的,別忘了在nioSocketAcceptor這個類的父類AbstractPollingIoAcceptor的構造方法中我們又去調用了AbstractPollingIoAcceptor的父類的構造方法,哪這個時候我們就去看看再哪里mina做了什么。
。。。不好意思在剛才說AbstractPollingIoAcceptor的構造函數的時候忘了說明一點就是在AbstractPollingIoAcceptor的構造函數中對NioProcessor進行了綁定,綁定有什么用呢,我們先看父類的構造函數中做了什么,再來說NioProcessor的用途。源碼加解釋:
是不是很掃興,這都已經是第三個父類了,怎么還沒有具體的實現,別灰心我們繼續往下跟,其實這個時候我們應該去想想,mina為什么這樣寫代碼,為什么要在父類的父類中取實現具體的操作,也許這也是一個設計模式或者模板,在這里我提出這個問題來咱們都去考慮考慮人家的代碼為什么這樣寫.哪在這里我們還是接着來跟源碼吧:
好了今天對mina服務端服務創建的一個過程做了一個大致簡單的介紹,其實並不是很詳細。我們目前暫時知道nioSocketAcceptor這個類的繼承及實現接口的關心,以及知道在初始化的過程中每個類是負責干什么的。下節我們重點對這個的細節進行一個學習介紹。對細節學習介紹后,我們就開始對客戶端請求到來的時候mina是如何處理這個請求的,我們知道在原生態的NIO中是通過selector這個大管家通關SelectionKey這個注冊的時間來監聽到是哪個通道發生的什么事件,然后我們根據發生的事件去做相應的操作,比如我們檢測到通道現在可讀,哪我們就從byteBuffer中將緩存的數據讀出來。好了今天就到這里吧,我的腦袋現在也有點暈暈的,待我好好理理再跟大家細細道來。明天見,一會換有一個設計模式--適配器模式的學習和博客的編寫。哎。。。革命尚未成功兄弟們還需努力啊。