Apache Mina Server是一個網路通訊應用程式框架,主要是對基於TCP/IP,UDP/IP協議棧的通訊架構,Mina可以協助快速開發高效能、高擴充性的網路通訊應用,Mina提供了事件驅動、非同步作業的編程模型。
Mina同時提供了網路通訊的Server端、Client端的封裝,無論是哪端,Mina在整個結構中都處於如下位置:
可見Mima的API將真正的網路通訊與文明的應用程式隔離開來,你只需要關心你要發送、接收的資料及你的商務邏輯即可。
同樣,無論是哪端,Mina的執行流程如下:
1)IoService:這個介面在一個線程上負責通訊端的建立,擁有自己的Selector,監聽是否有新串連被建立。
2) IoProcessor:這個介面在另一個線程上負責檢查是否有資料在通道上讀寫,也就是說它也擁有自己的Selector。
3) IoFilter:這個介面定義一組攔截器,這些攔截器可以包括日誌輸出、黑名單過濾、資料編碼、解碼等,其中編碼、解碼最為重要,也是你要使用Mina時最關注的地方。
4) IoHandler:這個介面負責編寫商務邏輯,也就是接收、發送資料的地方。
執行個體:簡單的TCPServer
/** * TCP SERVER * @function : * @author :jy * @company :萬裡網 * @date :2011-7-23 */public class MyServer {public static IoAcceptor acceptor = null;/** * @param args * @throws IOException */public static void main(String[] args) throws IOException {acceptor = new NioSocketAcceptor();acceptor.getSessionConfig().setReadBufferSize(2048);//讀緩衝區大小acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);//進入空閑時間acceptor.getSessionConfig().setUseReadOperation(true);//資料可讀acceptor.getSessionConfig().setWriteTimeout(30);//寫逾時時間//字元過濾器acceptor.getFilterChain().addLast("codec1", new ProtocolCodecFilter(new TextLineCodecFactory()));//acceptor.getFilterChain().addLast("myIoFilter", new ReferenceCountingFilter(new MyIoFilter()));//acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CmssSipcCodecFactory(Charset.forName("UTF-8"))));//acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new FlightCodecFactory(Charset.forName("UTF-8"))));//綁定商務邏輯acceptor.setHandler(new MyIoHandler());acceptor.bind(new InetSocketAddress(9123));//監聽連接埠號碼}}
簡單的Client:
/** * @function : * @author :jy * @company :萬裡網 * @date :2011-7-24 */public class MyClient {/** * @param args * @throws IOException */public static void main(String[] args) throws IOException {IoConnector conneector = new NioSocketConnector();conneector.setConnectTimeoutMillis(30000);//conneector.getFilterChain().addLast("codec1", new ProtocolCodecFilter(new TextLineCodecFactory()));//conneector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CmssSipcCodecFactory(Charset.forName("UTF-8"))));conneector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new FlightCodecFactory(Charset.forName("UTF-8"))));conneector.getSessionConfig().setUseReadOperation(true);conneector.setHandler(new MyClientHandler());conneector.connect(new InetSocketAddress("localhost", 9123));}}
註:TCP Server與TCP Client必須都綁定Hanndler,否則會拋出異常。
Server Handler:myIoHandler
/** * @function : * @author :jy * @company :萬裡網 * @date :2011-7-23 */public class MyIoHandler extends IoHandlerAdapter {private final static Logger log = LoggerFactory.getLogger(MyIoHandler.class);/** * 接收到訊息時調用的方法,也就是用於接收資訊的方法。 * message一般是一個IoBuffer類,如果你使用了協議編碼解碼器,那麼可以強制轉換為你需要的類型。 * 通常都會使用協議轉碼器的。 * 例如:使用TextLineCodecFactory協議轉碼器,可以強制轉換message為String類型。 */@Overridepublic void messageReceived(IoSession session, Object message){Flight sms = (Flight)message;//String sms = (String) message;log.info("The message recevied is [" + sms + "]");//session.write(new java.util.Date());//session.close(true);//session.write(session.getAttribute("test"));//if(str.equals("all")){////sendAll();//}////if(str.endsWith("quit")){//session.close(true);//return;//}}///**// * 這個方法當一個Session對象被建立的時候被調用。// * 對於TCP串連來說,串連被接受的時候調用,但要注意此時TCP串連並未被建立,也就是串連的對象IoSession被建立完畢// * 的時候,回調這個方法。// * 對於UDP來說,當有資料包收到的時候回調這個方法,因為UDP是不需連線的。// *///@Override//public void sessionCreated(IoSession session){//session.write("welcome!\r");//}///** * 當程式自身出現異常時回調,一般這裡關閉IoSession */@Overridepublic void exceptionCaught(IoSession session, Throwable able) throws Exception {able.printStackTrace();}/////**// * 當發送訊息成功時調用這個方法。// * 注意,這裡是發送成功之後,也就是說發送訊息時不能用這個發方法的。// *///@Override//public void messageSent(IoSession arg0, Object arg1) throws Exception {//// TODO Auto-generated method stub////}/////**// * 對於TCP來說,串連被關閉時,調用這個方法。// * 對於UDP來說,IoSession的close()方法被調用時才會毀掉這個方法。// *///@Override//public void sessionClosed(IoSession arg0) throws Exception {//// TODO Auto-generated method stub////}/////**// * 當IoSession的通道進入空閑狀態時調用。// * 對於UDP協議來說,這個方法始終不會被調用。// *///@Override//public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception {//// TODO Auto-generated method stub////}/////**// * 當串連被開啟時調用,它總是在sessionCreated()方法之後被調用。// * 對於TCP,它是在串連被建立之後調用,可以在這裡執行一些認證、發送資料操作等。// * 對於UDP,這個方法與sessionCreated()沒區別,但是緊跟其後執行。如果你每隔一段時間,發送一些資料,那麼// * sessionCreated()方法只會在第一次調用,但是sessionOpened()方法每次都會被調用。// *///@Override//public void sessionOpened(IoSession arg0) throws Exception {//// TODO Auto-generated method stub////}}
Client Hanlder:MyClientHandler
/** * @function : * @author :jy * @company :萬裡網 * @date :2011-7-24 */public class MyClientHandler extends IoHandlerAdapter {/* (non-Javadoc) * @see org.apache.mina.core.service.IoHandler#sessionCreated(org.apache.mina.core.session.IoSession) */@Overridepublic void sessionCreated(IoSession session) throws Exception {//SmsObject sms = new SmsObject();//sms.setSender("13721047855");//sms.setReceiver("15855533814");//sms.setMessage("hello MiNa");//session.write(sms);//Flight flight = new Flight();//flight.setFirstCity("SHA");//flight.setFirstDay("2011-07-28");//flight.setFlightway("DOBUBLE");//flight.setSecondCity("BJS");//flight.setSecondDay("2011-07-29");//flight.setThirdCity("SHA");//session.write(flight);//在建立了自訂資料Encode、Decode後,可以發送對象。session.write("hello Mina");}}