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對象),該怎麼辦呢?按照上面的說明,你有如下兩種辦法:

# 加入戰隊
微信公眾號

主題

# 加入戰隊
微信公眾號
