Android使用Apach Mina入門讀書(一)

来源:http://www.cnblogs.com/allensong815260/archive/2016/04/27/5440687.html
-Advertisement-
Play Games

最近開發一個項目需要用到Client(Android)透過Socket與Server通訊,網上有看到Apache封裝好的Socket通訊包,初步學習。 內容主要來源於(MINA官方教程(中文版)) 1.網路應用架構: 基於ApacheMINA的網路應用有三個層次,分別是I/O服務、I/O過濾器和I/ ...


最近開發一個項目需要用到Client(Android)透過Socket與Server通訊,網上有看到Apache封裝好的Socket通訊包,初步學習。

內容主要來源於(MINA官方教程(中文版))

1.網路應用架構:

基於ApacheMINA的網路應用有三個層次,分別是I/O服務、I/O過濾器和I/O處理器:
I/O服務:I/O服務用來執行實際的I/O操作。ApacheMINA已經提供了一系列支持不同協議的I/O服務,如TCP/IP、UDP/IP、串口和虛擬機內部的管道等。開發人員也可以實現自己的I/O服務。
I/O過濾器:I/O服務能夠傳輸的是位元組流,而上層應用需要的是特定的對象與數據結構。
   I/O過濾器用來完成這兩者之間的轉換。I/O過濾器的另外一個重要作用是對輸入輸出的數據進行處理,滿足橫切的需求。多個I/O過濾器串聯起來,形成I/O過濾器鏈。
I/O處理器:I/O處理器用來執行具體的業務邏輯。對接收到的消息執行特定的處理。創建一個完整的基於ApacheMINA的網路應用,需要分別構建這三個層次。

2.完成Client代碼初始化四步驟:

    //第一步:創建連接對象:
    SocketConnector connector = new NioSocketConnector();
   
     //第二步:給該連接對象設置處理對象:(IoHandlerAdapter)
    ClientHandler handler = new ClientHandler();
    connector.setHandler(handler);
  

    // 第三步:添加過濾器:
    connector.getFilterChain().addLast("codec",
        new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"),
            LineDelimiter.WINDOWS.getValue(), LineDelimiter.WINDOWS.getValue())));   


    //第四步:綁定即將通信對象:
    connector.connect(new InetSocketAddress("192.168.1.101", 5260));

3. I/O服務(IoService是I/O服務的介面,繼承 IoAcceptor)

I/O服務用來執行真正的I/O操作,以及管理I/O會話。根據所使用的數據傳輸方式的不同,有不同的I/O服務的實現。由於I/O服務執行的是輸入和輸出兩種操作,實際上有兩種具體的子類型。一種稱為“I/O接受器(I/Oacceptor)”,用來接受連接,一般用在伺服器的實現中;另外一種稱為“I/O連接器(I/Oconnector)”,用來發起連接,一般用在客戶端的實現中。

表1.IoService中的重要方法方法說明
setHandler(IoHandlerhandler):設置I/O處理器。該I/O處理器會負責處理該I/O服務所管理的所有I/O會話產生的I/O事件。getFilterChain()獲取I/O過濾器鏈,可以對I/O過濾器進行管理,包括添加和刪除I/O過濾器。
getManagedSessions():獲取該I/O服務所管理的I/O會話。

I/O連接器 Code Example:

SocketConnectorconnector=newNioSocketConnector();

connector.setConnectTimeoutMillis(CONNECT_TIMEOUT);
connector.getFilterChain().addLast("logger",newLoggingFilter());

connector.getFilterChain().addLast("protocol",
newProtocolCodecFilter(newTetrisCodecFactory()));
ConnectFutureconnectFuture=connector.connect(newInetSocketAddress(host,port));

connectFuture.awaitUninterruptibly();

4.I/O會話(IoSession)

I/O會話表示一個活動的網路連接,與所使用的傳輸方式無關。I/O會話可以用來存儲用戶自定義的與應用相關的屬性。這些屬性通常用來保存應用的狀態信息,還可以用來在I/O過濾器和I/O處理器之間交換數據。I/O會話在作用上類似於Servlet規範中的HTTP會話。

表2.IoSession中的重要方法方法說明:
close(booleanimmediately):關閉當前連接。如果參數immediately為true的話,連接會等到隊列中所有的數據發送請求都完成之後才關閉;否則的話就立即關閉。
getAttribute(Objectkey):從I/O會話中獲取鍵為key的用戶自定義的屬性。
setAttribute(Objectkey,Objectvalue):將鍵為key,值為value的用戶自定義的屬性存儲到I/O會話中。
removeAttribute(Objectkey):從I/O會話中刪除鍵為key的用戶自定義的屬性。
write(Objectmessage):將消息對象message發送到當前連接的對等體。該方法是非同步的,當消息被真正發送到對等體的時候,IoHandler.messageSent(IoSession,Object)會被調用。如果需要的話,也可以等消息真正發送出去之後再繼續執行後續操作。

這個介面有如下常用的方法:
A. WriteFuture write(Object message):這個方法用於寫數據,該操作是非同步的。
B. CloseFuture close(boolean immediately):這個方法用於關閉IoSession,該操作也是非同步的,參數指定true 表示立即關閉,否則就在所有的寫操作都flush 之後再關閉。
C. Object setAttribute(Object key,Object value):這個方法用於給我們向會話中添加一些屬性,這樣可以在會話過程中都可以使用,類似於HttpSession 的setAttrbute()方法。IoSession 內部使用同步的HashMap 存儲你添加的自定義屬性。

5.I/O過濾器(IoFilterAdapter)

從I/O服務發送過來的所有I/O事件和請求,在到達I/O處理器之前,會先由I/O過濾器鏈中的I/O過濾器進行處理。過濾器可以在很多情況下使用,比如記錄日誌、性能分析、訪問控制、負載均衡和消息轉換等。過濾器非常適合滿足網路應用中各種橫切的非功能性需求。在一個基於ApacheMINA的網路應用中,一般存在多個過濾器。這些過濾器互相串聯,形成鏈條,稱為過濾器鏈。每個過濾器依次對傳入的I/O事件進行處理。當前過濾器完成處理之後,由過濾器鏈中的下一個過濾器繼續處理。當前過濾器也可以不調用下一個過濾器,而提前結束,這樣I/O事件就不會繼續往後傳遞。比如負責用戶認證的過濾器,如果遇到未認證的對等體發出的I/O事件,則會直接關閉連接。這可以保證這些事件不會通過此過濾器到達I/O處理器。

表3.IoFilter中與過濾器的生命周期相關的方法

init():當過濾器第一次被添加到過 濾器鏈中的時候,此方法被調用。用來完成過濾器的初始化工作。

onPreAdd(IoFilterChainparent,Stringname,IoFilter.NextFilternextFilter): 當過濾器即將被添加到過濾 器鏈中的時候,此方法被調用。

onPostAdd(IoFilterChainparent,String name,IoFilter.NextFilternextFilter):當過濾器已經被添加到過濾器鏈中之後,此方法被調用

onPreRemove(IoFilterChainparent,Stringname,IoFilter.NextFilternextFilter):當過濾器即將被從過濾器鏈中刪除的時候,此方法被調用。
onPostRemove(IoFilterChainparent,Stringname,IoFilter.NextFilternextFilter):當過濾器已經被從過濾器鏈中刪除的時候,此方法被調用。
destroy():當過濾器不再需要的時候,它將被銷毀,此方法被調用

參數parent表示包含此過濾器的過濾器鏈,參數name表示過濾器的名稱,參數nextFilter表示過濾器鏈中的下一個過濾器。

filterClose(IoFilter.NextFilternextFilter,IoSessionsession):濾對IoSession的close方法的調用。
filterWrite(IoFilter.NextFilternextFilter,IoSessionsession,WriteRequestwriteRequest):濾對IoSession的write方法的調用。
exceptionCaught(IoFilter.NextFilternextFilter,IoSessionsession,Throwablecause):濾對IoHandler的exceptionCaught方法的調用。

messageReceived(IoFilter.NextFilternextFilter,IoSessionsession,Objectmessage):過濾對IoHandler的messageReceived方法的調用。

messageSent(IoFilter.NextFilternextFilter,IoSessionsession,WriteRequestwriteRequest):過濾對IoHandler的messageSent方法的調用。

sessionClosed(IoFilter.NextFilternextFilter,IoSessionsession):過濾對IoHandler的sessionClosed方法的調用。
sessionCreated(IoFilter.NextFilternextFilter,IoSessionsession):過濾對IoHandler的sessionCreated方法的調用。
sessionIdle(IoFilter.NextFilternextFilter,IoSessionsession,IdleStatusstatus):過濾對IoHandler的sessionIdle方法的調用。

sessionOpened(IoFilter.NextFilternextFilter,IoSessionsession):過濾對IoHandler的sessionOpened方法的調用。

code example:

public void messageReceived(NextFilternextFilter,IoSessionsession,Objectmessage){
if(!isON(session)){
    nextFilter.messageReceived(session,message);

}else{
           endSession(session);

}

}
private void endSession(IoSessionsession){
    session.close(true);

}

6.過濾器鏈(IoFilterChain)

過濾器只有在添加到過濾器鏈中的時候才起作用。過濾器鏈是過濾器的容器。過濾器鏈與I/O會話是一一對應的關係.

IoFilterChain介面的方法方法說明:
addFirst(String name,IoFilterfilter filter):將指定名稱的過濾器添加到過濾器鏈的開頭。
addLast(String name,IoFilterfilter filter):將指定名稱的過濾器添加到過濾器鏈的末尾。

contains(String name)判斷過濾器鏈中是否包含指定名稱的過濾器。

get(String name):從過濾器鏈中獲取指定名稱的過濾器。

remove(String name):從過濾器鏈中刪除指定名稱的過濾器。
replace(String name,IoFilter newFilter):用過濾器newFilter替換掉過濾器鏈中名為name的過濾器。

getSession():獲取與過濾器鏈一一對應的I/O會話

7.I/O處理器(IoHandlerAdapter)

I/O事件通過過濾器鏈之後會到達I/O處理器。I/O處理器中與I/O事件對應的方法會被調用。ApacheMINA中org.apache.mina.core.service.IoHandler是I/O處理器要實現的介面,一般情況下,只需要繼承自org.apache.mina.core.service.IoHandlerAdapter並覆寫所需方法即可。

IoHandler介面的方法:

sessionCreated(IoSessionsession)當有新的連接建立的時候,該方法被調用。

sessionOpened(IoSessionsession)當有新的連接打開的時候,該方法被調用。該方法在sessionCreated之後被調用。
sessionClosed(IoSessionsession)當連接被關閉的時候,此方法被調用。

sessionIdle(IoSessionsession,IdleStatusstatus)當連接變成閑置狀態的時候,此方法被調用。
exceptionCaught(IoSessionsession,Throwablecause)當I/O處理器的實現或是ApacheMINA中有異常拋出的時候,此方法被調用。
messageReceived(IoSessionsession,Objectmessage)當接收到新的消息的時候,此方法被調用。

messageSent(IoSessionsession,Objectmessage)當消息被成功發送出去的時候,此方法被調用。

其中

1.sessionCreated和sessionOpened的區別:

sessionCreated方法是由I/O處理線程來調用的,而sessionOpened是由其它線程來調用的。因此從性能方面考慮,不要在sessionCreated方法中執行過多的操作。

2.sessionIdle,預設情況下,閑置時間設置是禁用的,也就是說sessionIdle並不會被調用。可以通過IoSessionConfig.setIdleTime(IdleStatus,int)來進行設置

 

常用方法:

1. WriteFuture的使用
IoSessionsession=...;//獲取I/O會話對象
WriteFuturefuture=session.write("HelloWorld");//發送數據

future.awaitUninterruptibly();//等待發送數據操作完成

if(future.isWritten()){
//數據已經被成功發送}else{
//數據發送失敗}
由於這樣的需求很常見,I/O處理器中提供了messageSent方法,當數據發送成功的時候,該方法會被調用。

2. JMX集成ApacheMINA可以集成JMX來對網路應用進行管理和監測。

MBeanServermBeanServer=ManagementFactory.getPlatformMBeanServer();

IoAcceptoracceptor=newNioSocketAcceptor();
IoServiceMBeanacceptorMBean=newIoServiceMBean(acceptor);

ObjectNameacceptorName=newObjectName(acceptor.getClass().getPackage().getName()+":type=acceptor,name="+acceptor.getClass().getSimpleName));

mBeanServer.registerMBean(acceptorMBean,acceptorName);


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 解決辦法:給img定義vertical align或者定義為塊狀。 最優的解決辦法是:定義vertical align,註:定義vertical align為middle時在IE6中大概還有一像素的頂邊距,最好為top或bottom。 還有種極端解決辦法就是:將父容器的字體大小為零,font siz ...
  • 有三種方法能夠確定瀏覽器視窗的尺寸(瀏覽器的視口,不包括工具欄和滾動條)。 對於Internet Explorer、Chrome、Firefox、Opera 以及 Safari: 瀏覽器視窗的內部高度:window.innerHeight 瀏覽器視窗的內部寬度:window.innerWidth 對 ...
  • 今天,開始學習第二節!!! 工欲善其事,必先利其器 react推薦我們使用webpack來打包文件,那麼我們就用吧!(其實真心不想用啊) 至於好處網上寫的天花亂墜的,大家自行解決啊... 這節主要就學習怎麼配置webpack了,這玩意我搗鼓了整整一天才弄的一知半解,哎,腦子差就是吃虧... 1.提前 ...
  • 在寫這篇文章之前,我詢問了在唯品會和騰訊的童鞋、以及公司裡面前端大神(深哥),對於設計稿切圖的詳細方法,經過對比驗證,得出設計稿轉換頁面單位尺寸方法步驟。我分別詢問下麵四個問題: 1. 設計稿的單位是什麼,一般大小是什麼? 2. 頁面長度單位用什麼,px、em、rem,還是混合,如果用rem,htm ...
  • 查看效果:http://hovertree.com/texiao/mobile/10/或者手機掃描二維碼查看效果: 效果圖:代碼如下: 轉自:http://hovertree.com/h/bjaf/loucldil.htm 推薦:http://hovertree.com/hvtart/bjae/jf ...
  • 在我們的項目中,有大量ajax查詢表單+結果列表的頁面,由於查詢結果是ajax返回的,當用戶點擊列表的某一項進入詳情頁之後,再點擊瀏覽器回退按鈕返回ajax查詢頁面,這時大家都知道查詢頁面的表單和結果都回到了預設狀態。 如果每次返回頁面都要重新輸入查詢條件,或有甚者還得轉到列表的第幾頁,那這種體驗用 ...
  • 外部樣式為: 通過 和 是無效的 要想修改div的width,可以通過如下這種方式: 要想修改多個屬性,可以這麼做: ...
  • 當我們使用activity加fragment的時候,每個界面都要建立一個fragment,每個fragment裡面都要重寫onCreate(),onCreateView(),onActivityCreated(),方法,我們新建一個基類BaseFragment來重寫這些方法 BaseFragment ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...