網路通訊架構Apache MINA

來源:互聯網
上載者:User

標籤:

Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 組織一個較新的項目,它為開發高效能和高可用性的網路應用程式提供了非常便利的架構。當前發行的 MINA 版本支援基於 Java NIO 技術的TCP/UDP 應用程式開發、串口通訊程式。 

Mina 的應用程式層: 

 

一個設計成熟的開源架構,總是會僅可能的減少侵入性,並在整個項目中找到合適的位置,而不應對整個項目的構架設計產生過多的影響,圖 1 就是 MINA 的應用程式層。和上節的 DEMO 中我們可以看到, MINA很好的把業務代碼和底層的通訊隔離了開來,我們要做的僅僅是建立好監聽,然後寫上我們需要實現的商務邏輯就OK 了。 

MINA 的內部流程: 



(1) IoService :這個介面在一個線程上負責通訊端的建立,擁有自己的 Selector ,監聽是否有串連被建立。 

(2) IoProcessor :這個介面在另一個線程上負責檢查是否有資料在通道上讀寫,也就是說它也擁有自己的Selector ,這是與我們使用 JAVA NIO 編碼時的一個不同之處,通常在 JAVA NIO 編碼中,我們都是使用一個 Selector ,也就是不區分 IoService 與 IoProcessor 兩個功能介面。另外, IoProcessor 也是 MINA 架構的核心組件之一 . 在 MINA 架構啟動時,會用一個線程池來專門產生線程,來負責調用註冊在 IoService 上的過濾器,並在過濾器鏈之後調用 IoHandler 。在預設情況 IoProcessor 會用N+1 個線程來輪流詢問監視的連接埠是否有資料傳送,其中 n 為 cpu 的核心個數。按一般的多線程設計概念來說,IoProcessor 的線程數是越多越好,但實際上並非如此,因為大家都知道, IO 的操作是非常佔用資源的,所以項目中的 IoProcessor 的線程數應該根據實際需要來定,而這個數字可以在產生 IoAcceptor 對象時進行設定。 EgIoAcceptor acceptor = new NioSocketAcceptor( N ); 

(3.) IoFilter :這個介面定義一組攔截器,這些攔截器可以包括日誌輸出、黑名單過濾,甚至是在過濾器鏈中利用 AOP 寫上許可權控制。資料的編碼( write 方向)與解碼( read 方向)等功能,其中資料的 encode 與 decode 是最為重要的、也是您在使用 Mina 時最主要關注的地方。 

(4.) IoHandler :這個介面負責編寫商務邏輯,也就是接收、發送資料的地方。如果大家把業務處理寫好,並寫好業務介面,真正要用時,只需要在此處替換即可,再次見證了 MINA 分層的徹底。 

其中 IoService 介面會專門起一個線程來輪詢是否有新的串連產生,一旦有串連產生則通知 IoProcessor, 而IoProcessor 則起 n+1 個線程來檢查串連是否有資料在上面讀寫。一旦有串連產生,並有資料讀寫,則通知 decode 或 encode ,進行報文的解碼或編碼,將處理後的報文再交給業務類進行業務處理。其中IoProcessor 是處理請求的分配,包括選擇 Selector ,逾時驗證,狀態記錄等。總之這個類和 IoService 一起配合工作,封裝了 NIO 底層的實現以及 MINA 架構內部的功能的支援 . 

結合執行個體,並根據以上的圖文講解,我們可以很輕易的總結出利用 MINA 編程的幾個大致步驟: 

建立一個實現了 IoService 介面的類 

設定一個實現了 IoFilter 介面的過濾器(如果有需要的情況下) 

設定一個 IoHandler 介面實現的處理類,用於處理事件(必須) 

對 IoService 綁定一個連接埠開始工作 


註:這一點請特別注意,因 IoProcessor 也是相當於輪詢機制,這導致在報文過長時,或其它原因導致報文不能一次傳輸完畢的情況下,必須儲存同一串連 ( 在 MINA 中是以 IoSession 類產生的對象 ) 的上一次狀態,這樣才能截取到一個完成的報文,而這也是 decode( 編碼器 ) 需要做的核心工作 。 


Mina 的使用: 

//Mina TCP 服務端 
package com.mina.test; 

import java.util.Date; 

import org.apache.mina.core.service.IoHandlerAdapter; 
import org.apache.mina.core.session.IdleStatus; 
import org.apache.mina.core.session.IoSession; 

public class TimeServerHandler extends IoHandlerAdapter { 
@Override 
public void sessionCreated(IoSession session) throws Exception { 
System.out.println("服務端與用戶端建立串連..."); 
super.sessionCreated(session); 


@Override 
public void sessionOpened(IoSession session) throws Exception { 
System.out.println("服務端與用戶端串連開啟..."); 
super.sessionOpened(session); 


@Override 
public void sessionClosed(IoSession session) throws Exception { 
System.out.println("服務端與用戶端串連關閉..."); 
super.sessionClosed(session); 


@Override 
public void messageSent(IoSession session, Object message) throws Exception { 
System.out.println("服務端發送資訊成功..."+message.toString()); 
super.messageSent(session, message); 


public void exceptionCaught(IoSession session, Throwable cause) 
throws Exception { 
System.out.println("服務端發送異常..."+cause.getMessage()); 
cause.printStackTrace(); 


public void messageReceived(IoSession session, Object message) 
throws Exception { 
String strMsg = message.toString(); 
System.out.println("服務端接收到的資料為: "+strMsg); 
if (strMsg.trim().equalsIgnoreCase("quit")) { 
session.close(); 
return; 
}
Date date = new Date(); 
session.write(date.toString()); 


public void sessionIdle(IoSession session, IdleStatus status) 
throws Exception { 
System.out.println("服務端進入空閑狀態... " + session.getIdleCount(status)); 




package com.mina.test; 

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 { 

private static final int PORT = 6488; 

public static void main(String[] args) throws IOException { 

//監聽即將到來的TCP串連,建立監控器 
IoAcceptor acceptor = new NioSocketAcceptor(); 
//設定攔截器 
acceptor.getFilterChain().addLast("logger", new LoggingFilter()); 
acceptor.getFilterChain().addLast( 
"codec", 
new ProtocolCodecFilter(new TextLineCodecFactory(Charset 
.forName("GBK")))); 
//設定處理類 
acceptor.setHandler(new TimeServerHandler()); 
    //設定配置 
acceptor.getSessionConfig().setReadBufferSize(2048); 
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10); 

//綁定的監聽連接埠,可多次綁定,也可同時綁定多個。 
acceptor.bind(new InetSocketAddress(PORT)); 
System.out.println("服務端啟動成功......連接埠號碼為: "+PORT); 





//Mina TCP用戶端 
package com.mina.test; 

import org.apache.mina.core.buffer.IoBuffer; 
import org.apache.mina.core.service.IoHandlerAdapter; 
import org.apache.mina.core.session.IdleStatus; 
import org.apache.mina.core.session.IoSession; 
import org.apache.mina.proxy.utils.ByteUtilities; 


public class TimeClientHandler extends IoHandlerAdapter { 

@Override 
public void messageReceived(IoSession iosession, Object message) 
throws Exception { 
IoBuffer bbuf = (IoBuffer) message; 
byte[] byten = new byte[bbuf.limit()]; 
bbuf.get(byten, bbuf.position(), bbuf.limit()); 
System.out.println("用戶端收到訊息" + ByteUtilities.asHex(byten)); 

@Override 
public void exceptionCaught(IoSession session, Throwable cause) 
throws Exception { 
System.out.println("用戶端異常"); 
super.exceptionCaught(session, cause); 

@Override 
public void messageSent(IoSession iosession, Object obj) throws Exception { 
System.out.println("用戶端訊息發送"); 
super.messageSent(iosession, obj); 

@Override 
public void sessionClosed(IoSession iosession) throws Exception { 
System.out.println("用戶端工作階段關閉"); 
super.sessionClosed(iosession); 

@Override 
public void sessionCreated(IoSession iosession) throws Exception { 
System.out.println("用戶端工作階段建立"); 
super.sessionCreated(iosession); 

@Override 
public void sessionIdle(IoSession iosession, IdleStatus idlestatus) 
throws Exception { 
System.out.println("用戶端工作階段休眠"); 
super.sessionIdle(iosession, idlestatus); 

@Override 
public void sessionOpened(IoSession iosession) throws Exception { 
System.out.println("用戶端工作階段開啟"); 
super.sessionOpened(iosession); 





package com.mina.test; 

import java.net.InetSocketAddress; 

import org.apache.mina.core.buffer.IoBuffer; 
import org.apache.mina.core.future.ConnectFuture; 
import org.apache.mina.core.service.IoConnector; 
import org.apache.mina.core.session.IoSession; 
import org.apache.mina.transport.socket.nio.NioSocketConnector; 

public class MinaTimeClient { 

private static final int PORT = 6488; 
private static IoConnector connector; 
private static IoSession session; 

public static void main(String[] args) throws Exception { 

TimeClientHandler clientHandler=new TimeClientHandler(); 
connector = new NioSocketConnector(); 
//設定處理類 
connector.setHandler(clientHandler); 
ConnectFuture connFuture = connector.connect(new InetSocketAddress("localhost", PORT)); 
connFuture.awaitUninterruptibly(); 
session = connFuture.getSession(); 
clientHandler.sessionOpened(session); 
System.out.println("TCP 用戶端啟動"); 

for(int j=0;j<5;j++){ // 發送兩遍 
byte[] bts = new byte[20]; 
for (int i = 0; i < 20; i++) { 
bts[i] = (byte) i; 

IoBuffer buffer = IoBuffer.allocate(20); 
// 自動擴容 
buffer.setAutoExpand(true); 
// 自動收縮 
buffer.setAutoShrink(true); 
buffer.put(bts); 
buffer.flip(); 
session.write(buffer); 
Thread.sleep(2000); 

// 關閉會話,待所有線程處理結束後 
connector.dispose(true); 



網路通訊架構Apache MINA

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.