Mina各組件介紹
- 2019 年 10 月 3 日
- 筆記
Mina各組件介紹
上一篇文章已經系統的介紹了Mina的運行流程,Apache推出的Mina性能上很是高效,上章節我們知道內部有很多的類,各個類之間的依賴也是很多,他們之家都是相互依賴。
下面主要看看各個類中的方法。本篇就當是Mina的文檔了。一下總結來源於網路:
IoService
- 這個介面是服務端IoAcceptor、客戶端IoConnector 的抽象,提供IO 服務和管理IoSession的功能,它有如下幾個常用的方法:
+ <font color="blue">TransportMetadata getTransportMetadata()</font>: 這個方法獲取傳輸方式的元數據描述資訊,也就是底層到底基於什麼的實現,譬如:nio、apr 等。 + <font color="blue">void addListener(IoServiceListener listener)</font>: 這個方法可以為IoService 增加一個監聽器,用於監聽IoService 的創建、活動、失效、空閑、銷毀,具體可以參考IoServiceListener 介面中的方法,這為你參與IoService 的生命周期提供了機會。 + <font color="blue">void removeListener(IoServiceListener listener)</font>: 這個方法用於移除上面的方法添加的監聽器。 + <font color="blue">void setHandler(IoHandler handler)</font>: 這個方法用於向IoService 註冊IoHandler,同時有getHandler()方法獲取Handler。 + <font color="blue">Map<Long,IoSession> getManagedSessions()</font>: 這個方法獲取IoService 上管理的所有IoSession,Map 的key 是IoSession 的id。 + <font color="blue">IoSessionConfig getSessionConfig()</font>: 這個方法用於獲取IoSession 的配置對象,通過IoSessionConfig 對象可以設置Socket 連接的一些選項。
IoAcceptor
- IoAcceptor主要就是bind方法。之前文章已經介紹過了。這裡一帶而過
IoConnector
- 這個介面是TCPClient 的介面, 主要增加了ConnectFuture connect(SocketAddressremoteAddress,SocketAddress localAddress)方法,用於與Server 端建立連接,第二個參數如果不傳遞則使用本地的一個隨機埠訪問Server 端。這個方法是非同步執行的,同樣的,也可以同時連接多個服務端。
IoSession
-
這個介面用於表示Server 端與Client 端的連接,IoAcceptor.accept()的時候返回實例。
-
WriteFuture write(Object message)
用於非同步寫數據
-
CloseFuture close(boolean immediately)
這個方法用於關閉IoSession,該操作也是非同步的,參數指定true 表示立即關閉,否則就在所有的寫操作都flush 之後再關閉
-
Object setAttribute(Object key,Object value)
這個方法用於給我們向會話中添加一些屬性,這樣可以在會話過程中都可以使用,類似於HttpSession 的setAttrbute()方法。IoSession 內部使用同步的HashMap 存儲你添加的自
定義屬性。 -
SocketAddress getRemoteAddress()
這個方法獲取遠端連接的套接字地址
-
void suspendWrite()
這個方法用於掛起寫操作,那麼有void resumeWrite()方法與之配對。對於read()方法同樣適用
-
ReadFuture read()
這個方法用於讀取數據, 但默認是不能使用的, 你需要調用IoSessionConfig 的setUseReadOperation(true)才可以使用這個非同步讀取的方法。一般我們不會用到這個方法,因為這個方法的內部實現是將數據保存到一個BlockingQueue,假如是Server 端,因為大量的Client 端發送的數據在Server 端都這麼讀取,那麼可能會導致記憶體泄漏,但對於Client,可能有的時候會比較便利
-
IoService getService()
這個方法返回與當前會話對象關聯的IoService 實例.關於TCP連接的關閉:無論在客戶端還是服務端,IoSession 都用於表示底層的一個TCP 連接,那麼你會發現無論是Server 端還是Client 端的IoSession 調用close()方法之後,TCP 連接雖然顯示關閉, 但主執行緒仍然在運行,也就是JVM 並未退出,這是因為IoSession 的close()僅僅是關閉了TCP的連接通道,並沒有關閉Server 端、Client 端的程式。你需要調用IoService 的dispose()方法停止Server 端、Client 端
-
IoSessionConfig
-
這個方法用於指定此次會話的配置,它有如下常用的方法
-
void setReadBufferSize(int size)
這個方法設置讀取緩衝的位元組數,但一般不需要調用這個方法,因為IoProcessor 會自動調整緩衝的大小。你可以調用setMinReadBufferSize()、setMaxReadBufferSize()方法,這樣無論IoProcessor 無論如何自動調整,都會在你指定的區間
-
void setIdleTime(IdleStatus status,int idleTime)
這個方法設置關聯在通道上的讀、寫或者是讀寫事件在指定時間內未發生,該通道就進入空閑狀態。一旦調用這個方法,則每隔idleTime 都會回調過濾器、IoHandler 中的sessionIdle()方法
-
void setWriteTimeout(int time)
這個方法設置寫操作的超時時間
-
void setUseReadOperation(boolean useReadOperation)
這個方法設置IoSession 的read()方法是否可用,默認是false
-
IoHandler
-
這個介面是你編寫業務邏輯的地方,從上面的示例程式碼可以看出,讀取數據、發送數據基本都在這個介面總完成,這個實例是綁定到IoService 上的,有且只有一個實例(沒有給一個IoService 注入一個IoHandler 實例會拋出異常)。它有如下幾個方法
-
void sessionCreated(IoSession session)
這個方法當一個Session 對象被創建的時候被調用。對於TCP 連接來說,連接被接受的時候調用,但要注意此時TCP 連接並未建立,此方法僅代表字面含義,也就是連接的對象IoSession 被創建完畢的時候,回調這個方法。對於UDP 來說,當有數據包收到的時候回調這個方法,因為UDP 是無連接的
-
void sessionOpened(IoSession session)
這個方法在連接被打開時調用,它總是在sessionCreated()方法之後被調用。對於TCP 來說,它是在連接被建立之後調用,你可以在這裡執行一些認證操作、發送數據等。對於UDP 來說,這個方法與sessionCreated()沒什麼區別,但是緊跟其後執行。如果你每隔一段時間,發送一些數據,那麼sessionCreated()方法只會在第一次調用,但是sessionOpened()方法每次都會調用
-
void sessionClosed(IoSession session)
對於TCP 來說,連接被關閉時,調用這個方法。對於UDP 來說,IoSession 的close()方法被調用時才會毀掉這個方法
-
void sessionIdle(IoSession session, IdleStatus status)
這個方法在IoSession 的通道進入空閑狀態時調用,對於UDP 協議來說,這個方法始終不會被調用
-
void exceptionCaught(IoSession session, Throwable cause)
這個方法在你的程式、Mina 自身出現異常時回調,一般這裡是關閉IoSession
-
void messageReceived(IoSession session, Object message)
接收到消息時調用的方法,也就是用於接收消息的方法,一般情況下,message 是一個IoBuffer 類,如果你使用了協議編解碼器,那麼可以強制轉換為你需要的類型。通常我們都是會使用協議編解碼器的, 就像上面的例子, 因為協議編解碼器是TextLineCodecFactory,所以我們可以強制轉message 為String 類型
-
void messageSent(IoSession session, Object message)
當發送消息成功時調用這個方法,注意這裡的措辭,發送成功之後,也就是說發送消息是不能用這個方法的。發送消息的時機:發送消息應該在sessionOpened()、messageReceived()方法中調用IoSession.write()方法完成。因為在sessionOpened()方法中,TCP 連接已經真正打開,同樣的在messageReceived()方法TCP 連接也是打開狀態,只不過兩者的時機不同。sessionOpened()方法是在TCP 連接建立之後,接收到數據之前發送;messageReceived()方法是在接收到數據之後發送,你可以完成依據收到的內容是什麼樣子,決定發送什麼樣的數據。因為這個介面中的方法太多,因此通常使用適配器模式IoHandlerAdapter,覆蓋你所感興趣的方法即可
-
IoBuffer
-
這個介面是對JAVA NIO 的ByteBuffer 的封裝,這主要是因為ByteBuffer 只提供了對基本數據類型的讀寫操作,沒有提供對字元串等對象類型的讀寫方法,使用起來更為方便,另外,ByteBuffer 是定長的,如果想要可變,將很麻煩。IoBuffer 的可變長度的實現類似於StringBuffer。IoBuffer 與ByteBuffer 一樣,都是非執行緒安全的。本節的一些內容如果不清楚,可以參考java.nio.ByteBuffer 介面。這個介面有如下常用的方法
-
static IoBuffer allocate(int capacity,boolean useDirectBuffer)
這個方法內部通過SimpleBufferAllocator 創建一個實例,第一個參數指定初始化容量,第二個參數指定使用直接緩衝區還是JAVA 記憶體堆的快取區,默認為false
-
void free()
釋放緩衝區,以便被一些IoBufferAllocator 的實現重用,一般沒有必要調用這個方法,除非你想提升性能(但可能未必效果明顯)
-
IoBuffer setAutoExpand(boolean autoExpand)
這個方法設置IoBuffer 為自動擴展容量,也就是前面所說的長度可變,那麼可以看出長度可變這個特性默認是不開啟的
-
IoBuffer setAutoShrink(boolean autoShrink)
這個方法設置IoBuffer為自動收縮,這樣在compact()方法調用之後,可以裁減掉一些沒有使用的空間。如果這個方法沒有被調用或者設置為false,你也可以通過調用shrink()方法手動收縮空間
-
IoBuffer order(ByteOrder bo)
這個方法設置是Big Endian 還是Little Endian,JAVA 中默認是Big Endian,C++和其他語言一般是Little Endian
-
IoBuffer asReadOnlyBuffer()
這個方法設置IoBuffer 為只讀的
-
Boolean prefixedDataAvailable(int prefixLength,int maxDataLength)
這個方法用於數據的最開始的1、2、4 個位元組表示的是數據的長度的情況,prefixLentgh表示這段數據的前幾個位元組(只能是1、2、4 的其中一個),代表的是這段數據的長度,maxDataLength 表示最多要讀取的位元組數。返回結果依賴於等式remaining()-prefixLength>=maxDataLength,也就是總的數據-表示長度的位元組,剩下的位元組數要比打算讀取的位元組數大或者相等
-
String getPrefixedString(int prefixLength,CharsetDecoder decoder)
如果上面的方法返回true,那麼這個方法將開始讀取表示長度的位元組之後的數據,注意要保持這兩個方法的prefixLength 的值是一樣的。G、H兩個方法在後面講到的PrefixedStringDecoder 中的內部實現使用。IoBuffer 剩餘的方法與ByteBuffer 都是差不多的,額外增加了一些便利的操作方法,例如:IoBuffer putString(String value,CharsetEncoder encoder)可以方便的以指定的編碼方式存儲字元串、InputStream asInputStream()方法從IoBuffer 剩餘的未讀的數據中轉為輸入流等
-
IoFuture
-
在Mina的很多操作中,你會看到返回值是XXXFuture,實際上他們都是IoFuture的子類,看到這樣的返回值,這個方法就說明是非同步執行的,主要的子類有ConnectFuture、CloseFuture 、ReadFuture 、WriteFuture 。這個介面的大部分操作都和java.util.concurrent.Future介面是類似的,譬如:await()、awaitUninterruptibly()等,一般我們常用awaitUninterruptibly()方法可以等待非同步執行的結果返回。這個介面有如下常用的方法
-
IoFuture addListener(IoFutureListener<?> listener)
這個方法用於添加一個監聽器, 在非同步執行的結果返回時監聽器中的回調方法operationComplete(IoFuture future),也就是說,這是替代awaitUninterruptibly()方法另一種等待非同步執行結果的方法,它的好處是不會產生阻塞
-
IoFuture removeListener(IoFutureListener<?> listener)
這個方法用於移除指定的監聽器
-
IoSession getSession()
這個方法返回當前的IoSession。舉個例子,我們在客戶端調用connect()方法訪問Server 端的時候,實際上這就是一個非同步執行的方法,也就是調用connect()方法之後立即返回,執行下面的程式碼,而不管是否連接成功。那麼如果我想在連接成功之後執行一些事情(譬如:獲取連接成功後的IoSession對象),該怎麼辦呢?按照上面的說明,你有如下兩種辦法:
-