天天看點

Mina2.0架構源碼剖析(四)

  前面幾篇介紹完了org.apache.mina.core.service這個包,現在進入org.apache.mina.core.session,這個包主要是圍繞IoSession展開的,包括會話的方方面面。

IoSession接口與底層的傳輸層類型無關(也就是不管是TCP還是UDP),它表示通信雙端的連接配接。它提供使用者自定義屬性,可以用于在過濾器和處理器之間交換使用者自定義協定相關的資訊。

每個會話都有一個Service為之提供服務,同時有一個Handler負責此會話的I/O事件處理。最重要的兩個方法是read和write,這兩個方法都是異步執行,若要真正完成必須在其傳回結果上進行等待。關閉會話的方法close是異步執行的,也就是應當等待傳回的CloseFuture,此外,還有另一種關閉方式closeOnFlush,它和close的差別是會先flush掉寫請求隊列中的請求資料,再關閉會話,但同樣是異步的。會話的讀寫類型是可配置的,在運作中可設定此端是否可讀寫。

一個會話主要包含兩個方面的資料,屬性映射圖,寫請求隊列,在這裡作者使用了工廠模式來為新建立的會話提供這些資料結構。

public interface IoSessionDataStructureFactory 

{

    IoSessionAttributeMap getAttributeMap(IoSession session) throws Exception;

    WriteRequestQueue getWriteRequestQueue(IoSession session) throws Exception;

}

      IoSessionConfig接口用于表示會話的配置資訊,主要包括:讀緩沖區大小,會話資料吞吐量,計算吞吐量時間間隔,指定會話端的空閑時間,寫請求操作逾時時間。在這個接口中有一個方法值得注意

void setUseReadOperation(boolean useReadOperation);

通過它來設定IoSession的read方法是否啟用,若啟用的話,則所有接收到的消息都會存儲在内部的一個阻塞隊列中,好處在于可以更友善使用者對資訊的處理,但對于某些應用來說并不管用,而且還會造成記憶體洩露,是以預設情況下這個選項是不開啟的。

IoSessionInitializer接口定義了一個回調函數,這在AbstractIoService這個類中的finishSessionInitialization方法中已經見識過它的使用了,用于把使用者自定義的會話初始化行為剝離出來。

public interface IoSessionInitializer<T extends IoFuture> 

    void initializeSession(IoSession session, T future);

 IoSessionRecycler接口為一個無連接配接的傳輸服務提供回收現有會話的服務,主要的方法是:

IoSession recycle(SocketAddress localAddress, SocketAddress remoteAddress);

一個會話的讀寫能力控制通過TrafficMask類來描述,主要是SelectionKey.OP_READ和SelectionKey.OP_WRITE結合。此類使用單例模式實作,還提供了與,或,非,異或等位操作來動态控制會話讀寫能力。

Mina中的I/O事件類型如下:

複制代碼

public enum IoEventType {

    SESSION_CREATED,//會話建立

    SESSION_OPENED,//會話打開

    SESSION_CLOSED,//會話關閉

    MESSAGE_RECEIVED,//接收到消息

    MESSAGE_SENT,//發送消息

    SESSION_IDLE,//空閑

    EXCEPTION_CAUGHT,//異常捕獲

    WRITE,

    CLOSE,

    SET_TRAFFIC_MASK,//設定讀寫能力

     IoEvent類實作了Runnable接口,表示一個I/O事件或一個I/O請求,包括事件類型,所屬的會話,事件參數值。最重要的方法就是fire,根據事件類型向會話的過濾器鍊上的衆多監聽者發出事件到來的信号。

    public void fire() {

        switch (getType()) {

        case MESSAGE_RECEIVED:

            getSession().getFilterChain().fireMessageReceived(getParameter());

            break;

        case MESSAGE_SENT:

            getSession().getFilterChain().fireMessageSent((WriteRequest) getParameter());

        case WRITE:

            getSession().getFilterChain().fireFilterWrite((WriteRequest) getParameter());

        case SET_TRAFFIC_MASK:

            getSession().getFilterChain().fireFilterSetTrafficMask((TrafficMask) getParameter());

        case CLOSE:

            getSession().getFilterChain().fireFilterClose();

        case EXCEPTION_CAUGHT:

            getSession().getFilterChain().fireExceptionCaught((Throwable) getParameter());

        case SESSION_IDLE:

            getSession().getFilterChain().fireSessionIdle((IdleStatus) getParameter());

        case SESSION_OPENED:

            getSession().getFilterChain().fireSessionOpened();

        case SESSION_CREATED:

            getSession().getFilterChain().fireSessionCreated();

        case SESSION_CLOSED:

            getSession().getFilterChain().fireSessionClosed();

        default:

            throw new IllegalArgumentException("Unknown event type: " + getType());

        }

    }

     Mina的會話中,有三種類型的閑置狀态:1)READER_IDLE ,這表示從遠端沒有資料到來,讀端空閑。2)WRITER_IDLE ,這表示寫端沒有在寫資料。3)BOTH_IDLE,讀端和寫端都空閑。 為了節約會話資源,可以讓使用者設定當空閑超過一定時間後關閉此會話,因為此會話可能在某一端出問題了,進而導緻另一端空閑超過太長時間。這可以通過使用IoSessionConfig.setIdleTime(IdleStatus,int)來完成,空閑時間閥值在會話配(IoSessionConfig)中設定。

前面介紹過IoSessionDataStructureFactor接口為會話提供所需要的資料結構,DefaultIoSessionDataStructureFactory是其一個預設實作類。它提供的寫請求隊列内部是一個初始大小為16的循環隊列,并且在插入隊列尾部和從隊列頭部取資料時都必須滿足互斥同步。

  private static class DefaultWriteRequestQueue implements WriteRequestQueue {

        private final Queue<WriteRequest> q = new CircularQueue<WriteRequest>(16);

        public void dispose(IoSession session) {

        public void clear(IoSession session) {

            q.clear();

        public synchronized boolean isEmpty(IoSession session) {

            return q.isEmpty();

        public synchronized void offer(IoSession session, WriteRequest writeRequest) {

            q.offer(writeRequest);

        public synchronized WriteRequest poll(IoSession session) {

            return q.poll();

本文轉自Phinecos(洞庭散人)部落格園部落格,原文連結:http://www.cnblogs.com/phinecos/archive/2008/12/04/1347663.html,如需轉載請自行聯系原作者