Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 組織一個較新的項目,它為開發高性能和高可用性的網絡應用程序提供了非常便利的框架。
這個框架的優點:
– 異步
– 無阻塞
– 事件驅動
– 支持TCP, UDP, APR, 串口…
– 通過 過濾器(Filters)實現擴展性
– 同時提供協議框架
總體框架
之前的一個項目用到了MINA,最近想再系統的整理一下,主要參考MINA 2.0 User Guide
基於MINA框架的應用程序架構應該是這樣的:
底層是基於JAVA的NIO 1.0實現的;
其核心部分架構是這樣的:
內部可以分為3 個層次:
I/O Service - 執行實際的I / O,可以選擇現成的Services如 (*Acceptor),也可以自己寫。
I/O Filter Chain - 這是一個由多個過濾器組成的過濾器鏈,在這個環節將字節數據轉換到特定的數據結構中(Filters/Transforms bytes into desired Data Structures and vice-versa)
I/O Handler - 實際的業務邏輯部分
Server端應用
對socket通信來說,使用比較廣泛的是基於Server端的應用,尤其是並發規模達到一定程度后,頗具挑戰性。那么我們來看一下,基於MINA框架的Server端應用:
1、IOAcceptor 監聽指定的端口,處理新的網絡連接;一旦一個新的連接到達后,IOAcceptor 就產生一個session,后續所有從這個IP和端口發送過來的請求就將通過這個Session被處理。
2、Session創建后,后續所有的數據包都被人到過濾器鏈中,通過過濾器將原始的字節碼轉變成高層的對象,這個環節PacketEncoder/Decoder就十分有用。
3、最后數據包或對象被傳送給Handler做業務邏輯處理;
Main.java:
public class Main {
private static final int PORT = 9123;
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
IoAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
acceptor.setHandler( new TimeServerHandler() );
acceptor.getSessionConfig().setReadBufferSize( 2048 );
acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
acceptor.bind(new InetSocketAddress(PORT));
}
}
1、創建IoAcceptor;
2、加入日志記錄和解碼的過濾器,其中日志過濾器用SL4J庫記錄信息,而編碼過濾器則解碼所有收到的信息。使用 new TextLineCodecFactory() 發送的信息迕行編碼,返是MINA自帶的,功能有限,只能處理文本戒者String類型。
3、設置ServerHandler,這里是一個自定義的Handler:TimeServerHandler;
4、設置Session的對應的I/O processor 讀緩存區大小2048;通常這個參數不需要設置;
5、設置空閑時間,這里的BOTH_IDLE
指EADER_IDLE
和 WRITER_IDLE
. 都為10秒;
6、綁定監聽端口9123;
TimeServerHandler.java:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package minatest1;
/**
*
* @author THINKPAD
*/
import java.util.Date;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
public class TimeServerHandler extends IoHandlerAdapter
{
@Override
public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
{
cause.printStackTrace();
}
@Override
public void messageReceived( IoSession session, Object message ) throws Exception
{
String str = message.toString();
if( str.trim().equalsIgnoreCase("quit") ) {
session.close();
return;
}
Date date = new Date();
session.write( date.toString() );
System.out.println("Message written...");
}
@Override
public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
{
System.out.println( "IDLE " + session.getIdleCount( status ));
}
}
這里主要有一下幾個主要的方法:
messageReceived(…),對接收到的消息(已經解碼)迕行下一步處理,這里對收到的字符串進行判斷,如果是”quit”則斷開連接;否則輸出當前時間的字符串格式;
exceptionCaught(…),自定義異常處理, 要不然異常會被“吃掉”;
sessionIdle,當Session處於IDLE狀態的時候,輸出空閑狀態次數;
測試,輸入:telnet 127.0.0.1 9123,隨便輸入一串字符串,顯示當前的時間:
IO Service
待續