天天看點

MINA架構

MINA 架構簡介

    Apache Mina Server 是一個網絡通信應用架構,也就是說,它主要是對基于TCP/IP、UDP/IP協定棧的通信架構(然,也可以提供JAVA 對象的序列化服務、虛拟機管道通信服務等),Mina 可以幫助我們快速開發高性能、高擴充性的網絡通信應用,Mina 提供了事件驅動、異步(Mina 的異步IO 預設使用的是JAVA NIO 作為底層支援)操作的程式設計模型。Mina 主要有1.x 和2.x 兩個分支,這裡我們講解最新版本2.0,如果你使用的是Mina 1.x,那麼可能會有一些功能并不适用。學習本文檔,需要你已掌握JAVA IO、JAVA NIO、JAVASocket、JAVA 線程及并發庫(java.util.concurrent.*)的知識。Mina 同時提供了網絡通信的Server 端、Client 端的封裝,無論是哪端,Mina 在整個網通通信結構中都處于如下的位置:

MINA架構

1。MINA 架構簡介

當客戶首次通路采用MINA編寫的程式時,IoAcceptor作為線程運作,負責接受來自客戶的請求。當有客戶請求連接配接時,建立一個Session,該Session與IoProcessor、SocketChannel以及IOService聯系起來。IoProcessor也作為另外一個線程運作,定時檢查客戶是否有資料到來,并對客戶請求進行處理,依次調用在IOService注冊的各個IoFilter,最後調用IoHandler進行最終的邏輯處理,再将處理後的結果Filter後傳回給用戶端。

2。IoSession

Session可以了解為伺服器與用戶端的特定連接配接,該連接配接由伺服器位址、端口以及用戶端位址、端口來決定。用戶端發起請求時,指定伺服器位址和端口,用戶端也會指定或者根據網絡路由資訊自動指定一個位址、自動配置設定一個端口。這個位址、端口對構成一個Session。

Session是伺服器端對這種連接配接的抽象,MINA對其進行了封裝,定義了IoSession接口,用來代表用戶端與伺服器的連接配接,在伺服器端來指代用戶端,實作對用戶端的操作、綁定與用戶端有關的資訊與對象。通過利用Session的這個概念,編寫程式時就可以在伺服器端非常友善地區分出是目前處理的是哪個用戶端的請求、維持用戶端的狀态資訊、可以實作用戶端之間互相通訊。

IoSession提供以下一些常用方法:

(1)setAttribute(Object key, Object value)      getAttribute(Object key)

設定/擷取使用者定義的屬性。

将該屬性與session聯系起來,友善以後處理使用者請求時使用。比如如果要求使用者登入後才能繼續進行操作,那麼在使用者成功登陸後,可以通過setAttribute()設定一個屬性,當使用者以後繼續請求時,可以通過getAttribute()擷取該屬性來判斷使用者是否登入。

(2)getRemoteAddress()

擷取遠端用戶端位址。

(3)getId() getCreationTime()    getLastIoTime() getConfig()

擷取Session的Id、建立時間、上次IO時間、配置資訊。

(4)write(Object message)

将資料發送給用戶端。

(5)close()

關閉Session。

說明:可以在Session中發送資料,但是Session沒有提供讀取資料的方法,讀取資料通過另一套機制在IoHandler的messageReceived()中實作。

3。Event

MINA可以看成是事件驅動的。通常在網絡通訊中,可以将整個過程劃分為幾個基本的階段,如建立連接配接、資料通信、關閉連接配接。

資料通信一般包括資料的發送和接收,由于在通信過程中,可能要多次發送和接收資料,以進行不同的業務互動。

不可能一直都接收和發送資料,是以就有Idle出現,在MINA中,如果在設定的時間内沒有資料發送或接收,那麼就會觸發一個Idle事件。

由于某種原因,可能會發生錯誤,導緻系統異常發生,引發exception。

是以,如果從事件發生的角度看的話,就可以在MINA中将通信看成由一個建立連結(sessionCreated 和 sessionOpened )、多個資料接收和發送、一個關閉連接配接事件以及多個Idle事件等7種事件組成的過程。

Session是對雙方互相通信的抽象,是以通信的過程就是一系列與Session相關的事件。

在MINA現在對TCP的實作中,sessionCreated 和 sessionOpened 沒有差別。是以嚴格來說,有6種類型的事件。

4。IoHandler

從以上MINA架構簡圖可以看出,對來自用戶端資料最終處理是在IoHandler中處理的。IoHandler封裝了來自用戶端不同僚件的處理,如果對某個事件感興趣,可以實作相應的方法,當該事件發生時,IoHandler中的方法就會被觸發執行。IoHandler總共有7個方法對應7個事件:

(1)void exceptionCaught(IoSession session, Throwable cause)

有異常發生時被觸發。

(2)void messageReceived(IoSession session, Object message)

有消息到達時被觸發,message代表接收到的消息。

(3)void messageSent(IoSession session, Object message)

發送消息時時被觸發,即在調用IoSession.write()時被觸發,message代表将要發送的消息。

(4)void sessionClosed(IoSession session)

當連接配接關閉時被觸發,即Session終止時被觸發。

(5)void sessionCreated(IoSession session)

當建立一個新連接配接時被觸發,即當開始一個新的Session時被觸發。

(6)void sessionIdle(IoSession session, IdleStatus status)

當連接配接空閑時被觸發。使用IoSessionConfig中的setIdleTime(IdleStatus status, intidleTime)方法可以設定session的空閑時間。如果該Session的空閑時間超過設定的值,該方法被觸發,可以通過session.getIdleCount(status)來擷取sessionIdle被觸發的次數。

(7)void sessionOpened(IoSession session)

當打開一個連接配接時被觸發。在目前的實作中,好像 sessionOpened 和 sessionCreated 沒有太大差別,sessionCreated 在 sessionOpened 之前被觸發。

IoHandler是一個接口,一般情況沒有必要直接實作該接口的每一個方法。MINA提供了一個IoHandlerAdapter類,該類實作了IoHandler要求的方法,但是都沒有做任何處理。當我們要編寫自己的Handler時,可以擴充IoHandlerAdapter,重寫我們關心的事件方法即可。比如,一般情況,我們比較關心是否接收到資料這個時間,那麼我們就可以覆寫messageReceived方法,不用管其他方法。

5。IoFilter

IoFilter用來對客戶的請求或發送給客戶的資料進行filter。與IoHandler一樣,Filter也是基于事件的,通過實作IoFilter接口,就可以對通信過程中的Session的事件進行處理。

Filter是一種鍊式結構,與IoHandler不同,處理每一種Session事件的函數中,除了傳入session對象外,還傳入了NextFilter對象,用來代表下一個Filter。一般情況,在處理結束後,調用下一個filter的相應方法作進一步處理。Filter也可以針對特定的通信或資料,不進行進一步處理,就可以不用調用NextFilter的相應方法。

除了與Session相應的7種事件外,在IoFilter中還可以對Filter的init、destroy以及add、remove等時間愛女作出處理。

MINA提供了一個IoFilterAdapter類,我們要編寫自己的Filter時,可以擴充IoFilterAdapter,不用直接實作IoFilter接口。

Apache MINA提供一個LoggingFilter類,用來log通信過程。

MINA 基本類的描述

在介紹架構之前先認識幾個接口:

IoAccepter 相當于網絡應用程式中的伺服器端

IoConnector 相當于用戶端

IoSession  目前用戶端到伺服器端的一個連接配接執行個體

IoHandler 業務處理邏輯

IoFilter  過濾器用于懸接通訊層接口與業務層接口

圖 1:MINA 的架構圖

MINA架構

在圖中的子產品鍊中,IoService 便是應用程式的入口,相當于我們前面代碼中的 IoAccepter,IoAccepter 便是 IoService 的一個擴充接口。IoService 接口可以用來添加多個 IoFilter,這些 IoFilter 符合責任鍊模式并由 IoProcessor 線程負責調用。而 IoAccepter 在 ioService 接口的基礎上還提供綁定某個通訊端口以及取消綁定的接口。在上面的例子中,我們是這樣使用 IoAccepter 的:

IoAcceptor acceptor = new SocketAcceptor();

相當于我們使用了 Socket 通訊方式作為服務的接入,目前版本的 MINA 還提供了除 SocketAccepter 外的基于資料封包通訊的 DatagramAccepter 以及基于管道通訊的 VmPipeAccepter。另外還包括序列槽通訊接入方式,目前基于序列槽通訊的接入方式已經在最新測試版的 MINA 中提供。你也可以自行實作 IoService 接口來使用自己的通訊方式。

而在上圖中最右端也就是 IoHandler,這便是業務處理子產品。相當于前面例子中的 HelloHandler 類。在業務處理類中不需要去關心實際的通訊細節,隻管處理用戶端傳輸過來的資訊即可。編寫 Handler 類就是使用 MINA 開發網絡應用程式的重心所在,相當于 MINA 已經幫你處理了所有的通訊方面的細節問題。為了簡化 Handler 類,MINA 提供了 IoHandlerAdapter 類,此類僅僅是實作了 IoHandler 接口,但并不做任何處理。

一個 IoHandler 接口中具有如下一些方法(摘自 MINA 的 API 文檔):

void exceptionCaught(IoSession session, Throwable cause)

                                                                                                                                                                                                                                                         當接口中其他方法抛出異常未被捕獲時觸發此方法void messageReceived(IoSession session, Object message)

                                                                                                                                                                                                                                                         當接收到用戶端的請求資訊後觸發此方法.void messageSent(IoSession session, Object message)

                                                                                                                                                                                                                                                         當資訊已經傳送給用戶端後觸發此方法.void sessionClosed(IoSession session)

                                                                                                                                                                                                                                                         當連接配接被關閉時觸發,例如用戶端程式意外退出等等.void sessionCreated(IoSession session)

                                                                                                                                                                                                                                                         當一個新用戶端連接配接後觸發此方法.void sessionIdle(IoSession session, IdleStatus status)

                                                                                                                                                                                                                                                         當連接配接空閑時觸發此方法.void sessionOpened(IoSession session)

                                                                                                                                                                                                                                                         當連接配接後打開時觸發此方法,一般此方法與 sessionCreated 會被同時觸發

前面我們提到 IoService 是負責底層通訊接入,而 IoHandler 是負責業務處理的。那麼 MINA 架構圖中的 IoFilter 作何用途呢?答案是你想作何用途都可以。但是有一個用途卻是必須的,那就是作為 IoService 和 IoHandler 之間的橋梁。IoHandler 接口中最重要的一個方法是 messageReceived,這個方法的第二個參數是一個 Object 型的消息,總所周知,Object 是所有 Java 對象的基礎,那到底誰來決定這個消息到底是什麼類型呢?答案也就在這個 IoFilter 中。在前面使用的例子中,我們添加了一個 IoFilter 是 new ProtocolCodecFilter(new TextLineCodecFactory()),這個過濾器的作用是将來自用戶端輸入的資訊轉換成一行行的文本後傳遞給 IoHandler,是以我們可以在 messageReceived 中直接将 msg 對象強制轉換成 String 對象。

上一篇: 入侵檢測
下一篇: 病毒檢測

繼續閱讀