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

來源:互聯網
上載者:User

   前面幾篇介紹完了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掉寫請求隊列中的請求資料,再關閉會話,但同樣是非同步。會話的讀寫
類型是可配置的,在運行中可設定此端是否可讀寫。

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

Java代碼
  1. public
     
    interface
     IoSessionDataStructureFactory   
  2. {  
  3.     IoSessionAttributeMap getAttributeMap(IoSession session) throws
     Exception;  
  4.     WriteRequestQueue getWriteRequestQueue(IoSession session) throws
     Exception;  
  5. }  
public interface IoSessionDataStructureFactory {    IoSessionAttributeMap getAttributeMap(IoSession session) throws Exception;    WriteRequestQueue getWriteRequestQueue(IoSession session) throws Exception;}


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

Java代碼
  1. void
     setUseReadOperation(
    boolean
     useReadOperation);  
void setUseReadOperation(boolean useReadOperation);


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

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

Java代碼
  1. public
     
    interface
     IoSessionInitializer<T 
    extends
     IoFuture>   
  2. {  
  3.     void
     initializeSession(IoSession session, T future);  
  4. }  
public interface IoSessionInitializer<T extends IoFuture> {    void initializeSession(IoSession session, T future);}


IoSessionRecycler介面為一個不需連線的傳輸服務提供回收現有會話的服務,主要的方法是:

Java代碼
  1. IoSession recycle(SocketAddress localAddress, SocketAddress remoteAddress);  
IoSession recycle(SocketAddress localAddress, SocketAddress remoteAddress);


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

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

Java代碼
  1. public
     
    enum
     IoEventType {  
  2.     SESSION_CREATED,//會話建立
      
  3.     SESSION_OPENED,//會話開啟
      
  4.     SESSION_CLOSED,//會話關閉
      
  5.     MESSAGE_RECEIVED,//接收到訊息
      
  6.     MESSAGE_SENT,//發送訊息
      
  7.     SESSION_IDLE,//空閑
      
  8.     EXCEPTION_CAUGHT,//異常捕獲
      
  9.     WRITE,  
  10.     CLOSE,  
  11.     SET_TRAFFIC_MASK,//設定讀寫能力
      
  12. }  
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,根據事件類型向會話的過濾器鏈上的眾多監聽者發出事件到來的訊號。

Java代碼
  1. public
     
    void
     fire() {  
  2.     switch
     (getType()) {  
  3.     case
     MESSAGE_RECEIVED:  
  4.         getSession().getFilterChain().fireMessageReceived(getParameter());  
  5.         break
    ;  
  6.     case
     MESSAGE_SENT:  
  7.         getSession().getFilterChain().fireMessageSent((WriteRequest) getParameter());  
  8.         break
    ;  
  9.     case
     WRITE:  
  10.         getSession().getFilterChain().fireFilterWrite((WriteRequest) getParameter());  
  11.         break
    ;  
  12.     case
     SET_TRAFFIC_MASK:  
  13.         getSession().getFilterChain().fireFilterSetTrafficMask((TrafficMask) getParameter());  
  14.         break
    ;  
  15.     case
     CLOSE:  
  16.         getSession().getFilterChain().fireFilterClose();  
  17.         break
    ;  
  18.     case
     EXCEPTION_CAUGHT:  
  19.         getSession().getFilterChain().fireExceptionCaught((Throwable) getParameter());  
  20.         break
    ;  
  21.     case
     SESSION_IDLE:  
  22.         getSession().getFilterChain().fireSessionIdle((IdleStatus) getParameter());  
  23.         break
    ;  
  24.     case
     SESSION_OPENED:  
  25.         getSession().getFilterChain().fireSessionOpened();  
  26.         break
    ;  
  27.     case
     SESSION_CREATED:  
  28.         getSession().getFilterChain().fireSessionCreated();  
  29.         break
    ;  
  30.     case
     SESSION_CLOSED:  
  31.         getSession().getFilterChain().fireSessionClosed();  
  32.         break
    ;  
  33.     default
    :  
  34.         throw
     
    new
     IllegalArgumentException(
    "Unknown event type: "
     + getType());  
  35.     }  
  36. }  
    public void fire() {        switch (getType()) {        case MESSAGE_RECEIVED:            getSession().getFilterChain().fireMessageReceived(getParameter());            break;        case MESSAGE_SENT:            getSession().getFilterChain().fireMessageSent((WriteRequest) getParameter());            break;        case WRITE:            getSession().getFilterChain().fireFilterWrite((WriteRequest) getParameter());            break;        case SET_TRAFFIC_MASK:            getSession().getFilterChain().fireFilterSetTrafficMask((TrafficMask) getParameter());            break;        case CLOSE:            getSession().getFilterChain().fireFilterClose();            break;        case EXCEPTION_CAUGHT:            getSession().getFilterChain().fireExceptionCaught((Throwable) getParameter());            break;        case SESSION_IDLE:            getSession().getFilterChain().fireSessionIdle((IdleStatus) getParameter());            break;        case SESSION_OPENED:            getSession().getFilterChain().fireSessionOpened();            break;        case SESSION_CREATED:            getSession().getFilterChain().fireSessionCreated();            break;        case SESSION_CLOSED:            getSession().getFilterChain().fireSessionClosed();            break;        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的迴圈
隊列,並且在插入隊列尾部和從隊列頭部取資料時都必須滿足互斥同步。

Java代碼
  1. private
     
    static
     
    class
     DefaultWriteRequestQueue 
    implements
     WriteRequestQueue {  
  2.       private
     
    final
     Queue<WriteRequest> q = 
    new
     CircularQueue<WriteRequest>(
    16
    );  
  3.       public
     
    void
     dispose(IoSession session) {  
  4.       }  
  5.       public
     
    void
     clear(IoSession session) {  
  6.           q.clear();  
  7.       }  
  8.       public
     
    synchronized
     
    boolean
     isEmpty(IoSession session) {  
  9.           return
     q.isEmpty();  
  10.       }  
  11.       public
     
    synchronized
     
    void
     offer(IoSession session, WriteRequest writeRequest) {  
  12.           q.offer(writeRequest);  
  13.       }  
  14.       public
     
    synchronized
     WriteRequest poll(IoSession session) {  
  15.           return
     q.poll();  
  16.       }  
  17.   } 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.