一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Apache Mina(一)

 黃建校 2016-10-15

Apache Mina是一個能夠幫助用戶開發(fā)高性能和高伸縮性網(wǎng)絡應用程序的框架。它通過Java nio技術基于TCP/IP和UDP/IP協(xié)議提供了抽象的、事件驅動的、異步的API。

Mina包的簡介:

org.apache.mina.core.buffer 用于緩沖區(qū)的IoBuffer
org.apache.mina.core.service
org.apache.mina.transport.*
用于提供連接的service
org.apache.mina.core.session 用于提供兩端狀態(tài)的session
org.apache.mina.core.filterchain
org.apache.mina.filter.*
用于攔截所有IO事件和請求的filter chain和各類攔截器(在IoService和IoHandler之間)
org.apache.mina.handler.* 用于處理IO事件的handler
org.apache.mina.core.future 用于實現(xiàn)異步IO操作的 future
org.apache.mina.core.polling 用于實現(xiàn)IO輪詢的的polling
org.apache.mina.proxy.* 用于實現(xiàn)代理的proxy

先介紹Mina幾個重要接口:

  • IoServiece :這個接口在一個線程上負責套接字的建立,擁有自己的 Selector,監(jiān)聽是否有連接被建立。
  • IoProcessor :這個接口在另一個線程上負責檢查是否有數(shù)據(jù)在通道上讀寫,也就是說它也擁有自己的 Selector,這是與我們使用 JAVA NIO 編碼時的一個不同之處,通常在 JAVA NIO 編碼中,我們都是使用一個 Selector,也就是不區(qū)分 IoService與 IoProcessor 兩個功能接口。另外,IoProcessor 負責調用注冊在 IoService 上的過濾器,并在過濾器鏈之后調用 IoHandler。  
  • IoAccepter :相當于網(wǎng)絡應用程序中的服務器端
  • IoConnector :相當于客戶端
  • IoSession :當前客戶端到服務器端的一個連接實例
  • IoHandler :這個接口負責編寫業(yè)務邏輯,也就是接收、發(fā)送數(shù)據(jù)的地方。這也是實際開發(fā)過程中需要用戶自己編寫的部分代碼。
  • IoFilter :過濾器用于懸接通訊層接口與業(yè)務層接口,這個接口定義一組攔截器,這些攔截器可以包括日志輸出、黑名單過濾、數(shù)據(jù)的編碼(write 方向)與解碼(read 方向)等功能,其中數(shù)據(jù)的 encode與 decode是最為重要的、也是你在使用 Mina時最主要關注的地方。

MIINA架構圖

在圖中的模塊鏈中,IoService 便是應用程序的入口,相當于我們前面代碼中的 IoAccepter,IoAccepter 便是 IoService 的一個擴展接口。IoService 接口可以用來添加多個 IoFilter,這些 IoFilter 符合責任鏈模式并由 IoProcessor 線程負責調用。而 IoAccepter 在 ioService 接口的基礎上還提供綁定某個通訊端口以及取消綁定的接口。

IoAcceptor acceptor = new SocketAcceptor();

上面代碼中,相當于我們使用了 Socket 通訊方式作為服務的接入,當前版本的 MINA 還提供了除 SocketAccepter 外的基于數(shù)據(jù)報文通訊的 DatagramAccepter 以及基于管道通訊的 VmPipeAccepter。另外還包括串口通訊接入方式,目前基于串口通訊的接入方式已經(jīng)在最新測試版的 MINA 中提供。你也可以自行實現(xiàn) IoService 接口來使用自己的通訊方式。

而在上圖中最右端也就是 IoHandler,這便是業(yè)務處理模塊。在業(yè)務處理類中不需要去關心實際的通訊細節(jié),只管處理客戶端傳輸過來的信息即可。編寫 Handler 類就是使用 MINA 開發(fā)網(wǎng)絡應用程序的重心所在,相當于 MINA 已經(jīng)幫你處理了所有的通訊方面的細節(jié)問題。為了簡化 Handler 類,MINA 提供了 IoHandlerAdapter 類,此類僅僅是實現(xiàn)了 IoHandler 接口,但并不做任何處理。

一個 IoHandler 接口中具有如下一些方法(摘自 MINA 的 API 文檔):

  • void exceptionCaught(IoSession session, Throwable cause)
    當接口中其他方法拋出異常未被捕獲時觸發(fā)此方法
  • void messageReceived(IoSession session, Object message)
    當接收到客戶端的請求信息后觸發(fā)此方法
  • void messageSent(IoSession session, Object message)
    當信息已經(jīng)傳送給客戶端后觸發(fā)此方法
  • void sessionClosed(IoSession session)
    當連接被關閉時觸發(fā),例如客戶端程序意外退出等等
  • void sessionCreated(IoSession session)
    當一個新客戶端連接后觸發(fā)此方法
  • void sessionIdle(IoSession session, IdleStatus status)
    當連接空閑時觸發(fā)此方法
  • void sessionOpened(IoSession session)
    當連接后打開時觸發(fā)此方法,一般此方法與 sessionCreated 會被同時觸發(fā)

前面我們提到 IoService 是負責底層通訊接入,而 IoHandler 是負責業(yè)務處理的。那么 MINA 架構圖中的 IoFilter 作何用途呢?答案是你想作何用途都可以。但是有一個用途卻是必須的,那就是作為 IoService 和 IoHandler 之間的橋梁。IoHandler 接口中最重要的一個方法是 messageReceived,這個方法的第二個參數(shù)是一個 Object 型的消息,總所周知,Object 是所有 Java 對象的基礎,那到底誰來決定這個消息到底是什么類型呢?答案也就在這個 IoFilter 中。在前面使用的例子中,我們添加了一個 IoFilter 是 new ProtocolCodecFilter(new TextLineCodecFactory()),這個過濾器的作用是將來自客戶端輸入的信息轉換成一行行的文本后傳遞給 IoHandler,因此我們可以在 messageReceived 中直接將 msg 對象強制轉換成 String 對象。

而如果我們不提供任何過濾器的話,那么在 messageReceived 方法中的第二個參數(shù)類型就是一個 byte 的緩沖區(qū),對應的類是 org.apache.mina.core.buffer.IoBuffer。雖然你也可以將解析客戶端信息放在 IoHandler 中來做,但這并不是推薦的做法,使原來清晰的模型又模糊起來,變得 IoHandler 不只是業(yè)務處理,還得充當協(xié)議解析的任務。

MINA自身帶有一些常用的過濾器,例如LoggingFilter(日志記錄)、BlackListFilter(黑名單過濾)、CompressionFilter(壓縮)、SSLFilter(SSL加密)等。

 

簡單地來講,就分為三層:

  1. I/O Service :負責處理I/O。
  2. I/O Filter Chain :負責編碼處理,字節(jié)到數(shù)據(jù)結構或數(shù)據(jù)結構到字節(jié)的轉換等,即非業(yè)務邏輯的操作。
  3. I/O Handle :負責處理業(yè)務邏輯。

客戶端的通信過程:

  1. 通過SocketConnector同服務器端建立連接。
  2. 鏈接建立之后I/O的讀寫交給了I/O Processor線程,I/O Processor是多線程的。
  3. 通過I/O Processor讀取的數(shù)據(jù)經(jīng)過IoFilterChain里所有配置的IoFilter,IoFilter進行消息的過濾,格式的轉換,在這個層面可以制定一些自定義的協(xié)議。
  4. 最后IoFilter將數(shù)據(jù)交給Handler進行業(yè)務處理,完成了整個讀取的過程。
  5. 寫入過程也是類似,只是剛好倒過來,通過IoSession.write寫出數(shù)據(jù),然后Handler進行寫入的業(yè)務處理,處理完成后交給IoFilterChain,進行消息過濾和協(xié)議的轉換,最后通過I/O Processor將數(shù)據(jù)寫出到socket通道。

IoFilterChain作為消息過濾鏈

  1. 讀取的時候是從低級協(xié)議到高級協(xié)議的過程,一般來說從byte字節(jié)逐漸轉換成業(yè)務對象的過程。
  2. 寫入的時候一般是從業(yè)務對象到字節(jié)byte的過程。

 客戶端通信過程   IoSession貫穿整個通信過程的始終 

創(chuàng)建服務器

復制代碼
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class MinaTimeServer {
    // 定義監(jiān)聽端口
    private static final int PORT = 6488;

    public static void main(String[] args) throws IOException {
        // 創(chuàng)建服務端監(jiān)控線程
        IoAcceptor acceptor = new NioSocketAcceptor();
        acceptor.getSessionConfig().setReadBufferSize(2048);
        acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
        // 設置日志記錄器
        acceptor.getFilterChain().addLast("logger", new LoggingFilter());
        // 設置編碼過濾器
        acceptor.getFilterChain().addLast(
            "codec",
            new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
        // 指定業(yè)務邏輯處理器
        acceptor.setHandler(new TimeServerHandler());
        // 設置端口號
        acceptor.bind(new InetSocketAddress(PORT));
        // 啟動監(jiān)聽線程
        acceptor.bind();
    }
}
復制代碼
復制代碼
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

/**
 * 服務器端業(yè)務邏輯
 */
public class TimeServerHandler extends IoHandlerAdapter {

    /**
     * 連接創(chuàng)建事件
     */
    @Override
    public void sessionCreated(IoSession session){
        // 顯示客戶端的ip和端口
        System.out.println(session.getRemoteAddress().toString());
    }
    
    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        cause.printStackTrace();
    }
    
    /**
     * 消息接收事件
     */
    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        String strMsg = message.toString();
        if (strMsg.trim().equalsIgnoreCase("quit")) {
            session.close(true);
            return;
        }
        // 返回消息字符串
        session.write("Hi Client!");
        // 打印客戶端傳來的消息內(nèi)容
        System.out.println("Message written : " + strMsg);
    }

    @Override
    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
        System.out.println("IDLE" + session.getIdleCount(status));
    }
    
}
復制代碼

客戶端

復制代碼
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

public class MinaTimeClient {
    
    public static void main(String[] args){
        // 創(chuàng)建客戶端連接器.
        NioSocketConnector connector = new NioSocketConnector();
        connector.getFilterChain().addLast("logger", new LoggingFilter());
        connector.getFilterChain().addLast("codec", 
                new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
        
        // 設置連接超時檢查時間
        connector.setConnectTimeoutCheckInterval(30);
        connector.setHandler(new TimeClientHandler());
        
        // 建立連接
        ConnectFuture cf = connector.connect(new InetSocketAddress("192.168.2.109", 6488));
        // 等待連接創(chuàng)建完成
        cf.awaitUninterruptibly();
        
        cf.getSession().write("Hi Server!");
        cf.getSession().write("quit");
        
        // 等待連接斷開
        cf.getSession().getCloseFuture().awaitUninterruptibly();
        // 釋放連接
        connector.dispose();
    }
}
復制代碼
復制代碼
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;

public class TimeClientHandler extends IoHandlerAdapter {

    public void messageReceived(IoSession session, Object message) throws Exception {
        String content = message.toString();
        System.out.println("client receive a message is : " + content);
    }

    public void messageSent(IoSession session, Object message) throws Exception {
        System.out.println("messageSent -> :" + message);
    }
    
}
復制代碼

 

 

 

http://my.oschina.net/ielts0909/blog?catalog=253154

http://www./mikechen/archive/2012/03/15/371938.html

http://dxf1122.blog.163.com/blog/static/54041004200931371414356/

http://blog.sina.com.cn/s/blog_7abc61de0100sdoi.html

http://mina./mina-project/documentation.html

http://wenku.baidu.com/view/b9af67c34028915f804dc292.html

http://wenku.baidu.com/view/46800bce0508763231121232.html

http://wenku.baidu.com/view/5ccc7935b90d6c85ec3ac6e7.html

 

 

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    精品少妇人妻av一区二区蜜桃| 日韩在线中文字幕不卡| 久久综合亚洲精品蜜桃| 国产三级黄片在线免费看| 韩国激情野战视频在线播放| 国产精品欧美激情在线| 国产亚洲视频香蕉一区| 91在线爽的少妇嗷嗷叫| 精品少妇人妻一区二区三区| 免费啪视频免费欧美亚洲| 日韩一区二区三区观看| 日本不卡片一区二区三区| 欧美大黄片在线免费观看| 五月天综合网五月天综合网| 欧美做爰猛烈叫床大尺度| 麻豆精品在线一区二区三区| 亚洲一区二区欧美在线| 最新日韩精品一推荐日韩精品| 黄色美女日本的美女日人| 久热香蕉精品视频在线播放| 九九久久精品久久久精品| 久久精品蜜桃一区二区av| 亚洲熟妇熟女久久精品 | 欧美日本道一区二区三区| 夫妻激情视频一区二区三区| 欧美日韩欧美国产另类| 国产成人在线一区二区三区| 久久亚洲精品中文字幕| 内用黄老外示儒术出处| 开心久久综合激情五月天| 加勒比东京热拍拍一区二区| 久久国产人妻一区二区免费| 丰满人妻一二区二区三区av | 欧美国产极品一区二区| 欧美午夜视频免费观看| 欧美日韩综合在线第一页 | 国产一区二区三区午夜精品| 色一情一伦一区二区三| 久久精品偷拍视频观看| 国产丝袜女优一区二区三区| 欧美丰满大屁股一区二区三区|