基本介紹:java
ApacheMINA2是一個開發高性能和高可伸縮性網絡應用程序的網絡應用框架。它提供了一個抽象的事件驅動的異步API,可使用TCP/IP、UDP/IP、串口和虛擬機內部的管道等傳輸方式。ApacheMINA2能夠做爲開發網絡應用程序的一個良好基礎。web
Mina的API將真正的網絡通訊與咱們的應用程序隔離開來,你只須要關心你要發送、編程
接收的數據以及你的業務邏輯便可。服務器
mina的基本架構:網絡
在圖中的模塊鏈中,IoService即是應用程序的入口,至關於咱們前面代碼中的IoAccepter,IoAccepter即是IoService的一個擴展接口。IoService接口能夠用來添加多個IoFilter,這些IoFilter符合責任鏈模式並由IoProcessor線程負責調用。而IoAccepter在ioService接口的基礎上還提供綁定某個通信端口以及取消綁定的接口。ioHandler則爲應用邏輯處理類。session
主要類以及接口:架構
(1.)IoService:這個接口在一個線程上負責套接字的創建,擁有本身的Selector,監併發
聽是否有鏈接被創建。app
(2.)IoProcessor:這個接口在另外一個線程上負責檢查是否有數據在通道上讀寫,也就是框架
說它也擁有本身的Selector,這是與咱們使用JAVANIO編碼時的一個不一樣之處,
一般在JAVANIO編碼中,咱們都是使用一個Selector,也就是不區分IoService
與IoProcessor兩個功能接口。另外,IoProcessor負責調用註冊在IoService上
的過濾器,並在過濾器鏈以後調用IoHandler。
(3.)IoFilter:這個接口定義一組攔截器,這些攔截器能夠包括日誌輸出、黑名單過濾、
數據的編碼(write方向)與解碼(read方向)等功能,其中數據的encode與decode
是最爲重要的、也是你在使用Mina時最主要關注的地方。
(4.)IoHandler:這個接口負責編寫業務邏輯,也就是接收、發送數據的地方。
(5.)IoSession:Session能夠理解爲服務器與客戶端的特定鏈接,該鏈接由服務器地址、端口以及客戶端地址、端口來決定。客戶端發起請求時,指定服務器地址和端口,客戶端也會指定或者根據網絡路由信息自動指定一個地址、自動分配一個端口。這個地址、端口對構成一個Session。Session是服務器端對這種鏈接的抽象,MINA對其進行了封裝,定義了IoSession接口,用來表明客戶端與服務器的鏈接,在服務器端來指代客戶端,實現對客戶端的操做、綁定與客戶端有關的信息與對象。經過利用Session的這個概念,編寫程序時就能夠在服務器端很是方便地區分出是當前處理的是哪一個客戶端的請求、維持客戶端的狀態信息、能夠實現客戶端之間相互通信。
一圖勝千言,MINA的核心類圖:
服務端代碼大體以下:
//初始化Acceptor—能夠不指定線程數量,MINA2裏面默認是CPU數量+2 //是你的工做主線程 NioSocketAcceptor acceptor = new NioSocketAcceptor(5); //創建線程池 java.util.concurrent.Executor threadPool = newFixedThreadPool(1500); //加入過濾器(Filter)到Acceptor acceptor.getFilterChain().addLast(「exector」, new ExecutorFilter(threadPool)); //編碼××× acceptor.getFilterChain().addLast(「codec」,new ProtocolCodecFilter(new WebDecoder(),new XmlEncoder())); //日誌 LoggingFilter filter = new LoggingFilter(); filter.setExceptionCaughtLogLevel(LogLevel.DEBUG); filter.setMessageReceivedLogLevel(LogLevel.DEBUG); filter.setMessageSentLogLevel(LogLevel.DEBUG); filter.setSessionClosedLogLevel(LogLevel.DEBUG); filter.setSessionCreatedLogLevel(LogLevel.DEBUG); filter.setSessionIdleLogLevel(LogLevel.DEBUG); filter.setSessionOpenedLogLevel(LogLevel.DEBUG); acceptor.getFilterChain().addLast(「logger」, filter); //設置的是主服務監聽的端口能夠重用 acceptor.setReuseAddress(true); //設置每個非主監聽鏈接的端口能夠重用 acceptor.getSessionConfig().setReuseAddress(true); //MINA2中,當啓動一個服務端的時候,要設定初始化緩衝區的長度,若是不設置這個值,系統默認爲2048,當客戶端發過來的消息超過設定值的時候, //MINA2的機制是分段接受的,將字符是放入緩衝區中讀取,因此在讀取消息的時候,須要判斷有多少次。這樣的好處就是能夠節省通信的流量。 //設置輸入緩衝區的大小 acceptor.getSessionConfig().setReceiveBufferSize(1024); //設置輸出緩衝區的大小 acceptor.getSessionConfig().setSendBufferSize(10240); //設置爲非延遲發送,爲true則不組裝成大包發送,收到東西立刻發出 acceptor.getSessionConfig().setTcpNoDelay(true); //設置主服務監聽端口的監聽隊列的最大值爲100,若是當前已經有100個鏈接,再新的鏈接來將被服務器拒絕 acceptor.setBacklog(100); acceptor.setDefaultLocalAddress(new InetSocketAddress(port)); //加入處理器(Handler)到Acceptor acceptor.setHandler(new YourHandler()); acceptor.bind();
//初始化Acceptor—能夠不指定線程數量,MINA2裏面默認是CPU數量+2 //是你的工做主線程 NioSocketAcceptor acceptor = new NioSocketAcceptor(5); //創建線程池 java.util.concurrent.Executor threadPool = newFixedThreadPool(1500); //加入過濾器(Filter)到Acceptor acceptor.getFilterChain().addLast("exector", new ExecutorFilter(threadPool)); //編碼××× acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new WebDecoder(),new XmlEncoder())); //日誌 LoggingFilter filter = new LoggingFilter(); filter.setExceptionCaughtLogLevel(LogLevel.DEBUG); filter.setMessageReceivedLogLevel(LogLevel.DEBUG); filter.setMessageSentLogLevel(LogLevel.DEBUG); filter.setSessionClosedLogLevel(LogLevel.DEBUG); filter.setSessionCreatedLogLevel(LogLevel.DEBUG); filter.setSessionIdleLogLevel(LogLevel.DEBUG); filter.setSessionOpenedLogLevel(LogLevel.DEBUG); acceptor.getFilterChain().addLast("logger", filter); //設置的是主服務監聽的端口能夠重用 acceptor.setReuseAddress(true); //設置每個非主監聽鏈接的端口能夠重用 acceptor.getSessionConfig().setReuseAddress(true); //MINA2中,當啓動一個服務端的時候,要設定初始化緩衝區的長度,若是不設置這個值,系統默認爲2048,當客戶端發過來的消息超過設定值的時候, //MINA2的機制是分段接受的,將字符是放入緩衝區中讀取,因此在讀取消息的時候,須要判斷有多少次。這樣的好處就是能夠節省通信的流量。 //設置輸入緩衝區的大小 acceptor.getSessionConfig().setReceiveBufferSize(1024); //設置輸出緩衝區的大小 acceptor.getSessionConfig().setSendBufferSize(10240); //設置爲非延遲發送,爲true則不組裝成大包發送,收到東西立刻發出 acceptor.getSessionConfig().setTcpNoDelay(true); //設置主服務監聽端口的監聽隊列的最大值爲100,若是當前已經有100個鏈接,再新的鏈接來將被服務器拒絕 acceptor.setBacklog(100); acceptor.setDefaultLocalAddress(new InetSocketAddress(port)); //加入處理器(Handler)到Acceptor acceptor.setHandler(new YourHandler()); acceptor.bind();
客戶端代碼大體以下:
客戶端的初始化和服務器端實際上是同樣的,就是初始化類不同,客戶端是做爲發送者的。
SocketConnector connector = new NioSocketConnector(); connector.getFilterChain().addLast(「codec」, new ProtocolCodecFilter(new XmlCodecFactory(Charset.forName(charsetName), null, sertType))); //指定線程池 connector.getFilterChain().addLast(「executor」, new ExecutorFilter()); //指定業務處理類 connector.setHandler(this);
SocketConnector connector = new NioSocketConnector(); connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new XmlCodecFactory(Charset.forName(charsetName), null, sertType))); //指定線程池 connector.getFilterChain().addLast("executor", new ExecutorFilter()); //指定業務處理類 connector.setHandler(this);
在IoHandler中定義了一些事件方法,好比messageReceived,sessionOpend,sessionCreated,exceptionCaught等,用戶只須要在方法內部實現對應的處理邏輯便可。
心跳機制:
mina自身帶的心跳機制好處在於,它附加了處理,讓心跳消息不會傳到業務層,在底層就完成了。
事件模型:
MINA能夠當作是事件驅動的。一般在網絡通信中,能夠將整個過程劃分爲幾個基本的階段,如創建鏈接、數據通訊、關閉鏈接。
數據通訊通常包括數據的發送和接收,因爲在通訊過程當中,可能要屢次發送和接收數據,以進行不一樣的業務交互。
不可能一直都接收和發送數據,所以就有Idle出現,在MINA中,若是在設定的時間內沒有數據發送或接收,那麼就會觸發一個Idle事件。
附錄:對與協議的理解,摘自ppt
http協議
對應於應用層
tcp協議
對應於傳輸層
ip協議
對應於網絡層
三者本質上沒有可比性。況且HTTP協議是基於TCP鏈接的。
TCP/IP是傳輸層協議,主要解決數據如何在網絡中傳輸;而HTTP是應用層協議,主要解決如何包裝數據。
咱們在傳輸數據時,能夠只使用傳輸層(TCP/IP),可是那樣的話,因爲沒有應用層,便沒法識別數據內容,若是想要使傳輸的數據有意義,則必須使用應用層協議,應用層協議不少,有HTTP、FTP、TELNET等等,也能夠本身定義應用層協議。WEB使用HTTP做傳輸層協議,以封裝HTTP文本信息,而後使用TCP/IP作傳輸層協議將它發送到網絡上。
Socket是對TCP/IP協議的封裝,Socket自己並非協議,而是一個調用接口(API),經過Socket,咱們才能使用TCP/IP協議。
這也就不難理解爲何有些內部的系統調用採用socket,而不是http。
自己web的這種系統,HTTP已經將報文信息封裝好了。各類JEE的WEB框架,都可以直接獲取報文中的信息,而socket方式,能夠雙方很方便的本身定義報文的內容,加密方式等等。
URL:應用層
SOCKET
:網絡傳輸層
Socket(套接字)
是一種基於網絡傳輸層的遠程進程間通訊編程接口,有操做系統提供一個套接字包含,主機名、端口號兩個部分。其中端口號是0~65535之間的一個整數。一般小於1024的端口號被統一分配給特定的網絡服務,如ftp服務,21;http服務,80;SMTP服務,25;POP3服務,110;telnet服務,23等等
套接字(socket)是通訊的基石,是支持TCP/IP協議的網絡通訊的基本操做單元。它是網絡通訊過程當中端點的抽象表示,包含進行網絡通訊必須的五種信息:鏈接使用的協議,本地主機的IP地址,本地進程的協議端口,遠地主機的IP地址,遠地進程的協議端口。
應用層經過傳輸層進行數據通訊時,TCP會遇到同時爲多個應用程序進程提供併發服務的問題。多個TCP鏈接或多個應用程序進程可能須要經過同一個
TCP協議端口傳輸數據。爲了區別不一樣的應用程序進程和鏈接,許多計算機操做系統爲應用程序與TCP/IP協議交互提供了套接字(Socket)接口。
因爲一般狀況下Socket鏈接就是TCP鏈接,所以Socket鏈接一旦創建,通訊雙方便可開始相互發送數據內容,直到雙方鏈接斷開。但在實際網絡應用中,客戶端到服務器之間的通訊每每須要穿越多箇中間節點,例如路由器、網關、防火牆等,大部分防火牆默認會關閉長時間處於非活躍狀態的鏈接而致使
Socket鏈接斷連,所以須要經過輪詢告訴網絡,該鏈接處於活躍狀態。
而HTTP鏈接使用的是「請求—響應」的方式,不只在請求時須要先創建鏈接,並且須要客戶端向服務器發出請求後,服務器端才能回覆數據。
不少狀況下,須要服務器端主動向客戶端推送數據,保持客戶端與服務器數據的實時與同步。此時若雙方創建的是Socket鏈接,服務器就能夠直接將數據傳送給客戶端;若雙方創建的是HTTP鏈接,則服務器須要等到客戶端發送一次請求後才能將數據傳回給客戶端,所以,客戶端定時向服務器端發送鏈接請求,不只能夠保持在線,同時也是在「詢問」服務器是否有新的數據,若是有就將數據傳給客戶端。