一:Mina概要 Apache Mina是一個能夠幫助用戶開發高性能和高伸縮性網絡應用程序的框架。它通過Java nio技術基于TCP/IP和UDP/IP協議提供了抽象的、事件驅動的、異步的API。
如下的特性:
1、 基于Java nio的TCP/IP和UDP/IP實現
基于RXTX的串口通信(RS232)
VM 通道通信
2、通過filter接口實現擴展,類似于Servlet filters
3、low-level(底層)和high-level(高級封裝)的api:
low-level:使用ByteBuffers
High-level:使用自定義的消息對象和解碼器
4、Highly customizable(易用的)線程模式(MINA2.0 已經禁用線程模型了):
單線程
線程池
多個線程池
5、基于java5 SSLEngine的SSL、TLS、StartTLS支持
6、負載平衡
7、使用mock進行單元測試
8、jmx整合
9、基于StreamIoHandler的流式I/O支持
10、IOC容器的整合:Spring、PicoContainer
11、平滑遷移到Netty平臺
二:實踐 首先講一下客戶端的通信過程:
1.通過SocketConnector同服務器端建立連接
2.鏈接建立之后I/O的讀寫交給了I/O Processor線程,I/O Processor是多線程的
3.通過I/O Processor讀取的數據經過IoFilterChain里所有配置的IoFilter,IoFilter進行消息的過濾,格式的轉換,在這個層面可以制定一些自定義的協議
4.最后IoFilter將數據交給Handler進行業務處理,完成了整個讀取的過程
5.寫入過程也是類似,只是剛好倒過來,通過IoSession.write寫出數據,然后Handler進行寫入的業務處理,處理完成后交給IoFilterChain,進行消息過濾和協議的轉換,最后通過I/O Processor將數據寫出到socket通道
IoFilterChain作為消息過濾鏈
1.讀取的時候是從低級協議到高級協議的過程,一般來說從byte字節逐漸轉換成業務對象的過程
2.寫入的時候一般是從業務對象到字節byte的過程
IoSession貫穿整個通信過程的始終
客戶端通信過程

1.創建服務器
package com.gewara.web.module.base;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.core.service.IoAcceptor;
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;
/**
* Mina服務器
*
* @author mike
*
* @since 2012-3-15
*/
public class HelloServer {
private static final int PORT = 8901;// 定義監聽端口
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 HelloServerHandler());
// 設置端口號
acceptor.setDefaultLocalAddress(new InetSocketAddress(PORT));
// 啟動監聽線程
acceptor.bind();
}
}
2.創建服務器端業務邏輯
package com.gewara.web.module.base;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
/**
* 服務器端業務邏輯
*
* @author mike
*
* @since 2012-3-15
*/public class HelloServerHandler
extends IoHandlerAdapter {
@Override
/**
* 連接創建事件
*/ public void sessionCreated(IoSession session){
// 顯示客戶端的ip和端口
System.out.println(session.getRemoteAddress().toString());
}
@Override
/**
* 消息接收事件
*/ public void messageReceived(IoSession session, Object message)
throws Exception{
String str = message.toString();
if (str.trim().equalsIgnoreCase("quit")){
// 結束會話
session.close(
true);
return;
}
// 返回消息字符串
session.write("Hi Client!");
// 打印客戶端傳來的消息內容
System.out.println("Message written

" + str);
}
}
3.創建客戶端
package com.gewara.web.module.base;
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;
/**
* Mina客戶端
*
* @author mike
*
* @since 2012-3-15
*/
public class HelloClient {
public static void main(String[] args){
// 創建客戶端連接器.
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 HelloClientHandler());
// 建立連接
ConnectFuture cf = connector.connect(new InetSocketAddress("192.168.2.89", 8901));
// 等待連接創建完成
cf.awaitUninterruptibly();
// 發送消息
cf.getSession().write("Hi Server!");
// 發送消息
cf.getSession().write("quit");
// 等待連接斷開
cf.getSession().getCloseFuture().awaitUninterruptibly();
// 釋放連接
connector.dispose();
}
}
4.客戶端業務邏輯
package com.gewara.web.module.base;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
public class HelloClientHandler extends IoHandlerAdapter {
@Override
/**
* 消息接收事件
*/
public void messageReceived(IoSession session, Object message) throws Exception{
//顯示接收到的消息
System.out.println("server message:"+message.toString());
}
}
5.先啟動服務器端,然后啟動客戶端
2012-03-15 14:45:41,456 INFO logging.LoggingFilter - CREATED
/192.168.2.89:2691
2012-03-15 14:45:41,456 INFO logging.LoggingFilter - OPENED
2012-03-15 14:45:41,487 INFO logging.LoggingFilter - RECEIVED: HeapBuffer[pos=0 lim=11 cap=2048: 48 69 20 53 65 72 76 65 72 21 0A]
2012-03-15 14:45:41,487 DEBUG codec.ProtocolCodecFilter - Processing a MESSAGE_RECEIVED
for session 1
Message written

Hi Server!
2012-03-15 14:45:41,487 INFO logging.LoggingFilter - SENT: HeapBuffer[pos=0 lim=0 cap=0: empty]
2012-03-15 14:45:41,487 INFO logging.LoggingFilter - RECEIVED: HeapBuffer[pos=0 lim=5 cap=2048: 71 75 69 74 0A]
2012-03-15 14:45:41,487 DEBUG codec.ProtocolCodecFilter - Processing a MESSAGE_RECEIVED
for session 1
2012-03-15 14:45:41,487 INFO logging.LoggingFilter - CLOSED
三:分析源碼
1.首先看服務器
// 創建服務端監控線程
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 HelloServerHandler());
// 設置端口號
acceptor.setDefaultLocalAddress(new InetSocketAddress(PORT));
// 啟動監聽線程
acceptor.bind();
1)先創建NioSocketAcceptor nio的接收器,談到Socket就要說到Reactor模式 當前分布式計算 Web Services盛行天下,這些網絡服務的底層都離不開對socket的操作。他們都有一個共同的結構:1. Read request2. Decode request3. Process service 4. Encode reply5. Send reply 
但這種模式在用戶負載增加時,性能將下降非常的快。我們需要重新尋找一個新的方案,保持數據處理的流暢,很顯然,事件觸發機制是最好的解決辦法,當有事件發生時,會觸動handler,然后開始數據的處理。
Reactor模式類似于AWT中的Event處理。
Reactor模式參與者
1.Reactor 負責響應IO事件,一旦發生,廣播發送給相應的Handler去處理,這類似于AWT的thread
2.Handler 是負責非堵塞行為,類似于AWT ActionListeners;同時負責將handlers與event事件綁定,類似于AWT addActionListener

并發系統常采用reactor模式,簡稱觀察者模式,代替常用的多線程處理方式,利用有限的系統的資源,提高系統的吞吐量。
可以看一下這篇文章,講解的很生動具體,一看就明白reactor模式的好處
http://daimojingdeyu.iteye.com/blog/828696 Reactor模式是編寫高性能網絡服務器的必備技術之一,它具有如下的優點: 1)響應快,不必為單個同步時間所阻塞,雖然Reactor本身依然是同步的; 2)編程相對簡單,可以最大程度的避免復雜的多線程及同步問題,并且避免了多線程/進程的切換開銷; 3)可擴展性,可以方便的通過增加Reactor實例個數來充分利用CPU資源; 4)可復用性,reactor框架本身與具體事件處理邏輯無關,具有很高的復用性; 2)其次,再說說NIO的基本原理和使用 NIO 有一個主要的類Selector,這個類似一個觀察者,只要我們把需要探知的socketchannel告訴Selector,我們接著做別的事情,當有事件發生時,他會通知我們,傳回一組 SelectionKey,我們讀取這些Key,就會獲得我們剛剛注冊過的socketchannel,然后,我們從這個Channel中讀取數據,放心,包準能夠讀到,接著我們可以處理這些數據。
Selector內部原理實際是在做一個對所注冊的channel的輪詢訪問,不斷的輪詢(目前就這一個算法),一旦輪詢到一個channel有所注冊的事情發生,比如數據來了,他就會站起來報告,交出一把鑰匙,讓我們通過這把鑰匙(SelectionKey表示 SelectableChannel 在 Selector 中的注冊的標記。 )來讀取這個channel的內容。