Apache MINA實戰之 牛刀小試
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
本文連結:http://blog.csdn.net/kongxx/article/details/7520259
Apache的MINA是一個被用來構建高效能和高可伸縮性應用程式的網路應用框架,它提供了一套統一的建立在Java NIO之上的事件驅動的非同步API。
對於MINA框架的瞭解,MINA官方的幾篇文章是必須要看的,如下:
* Application Architecture http://mina.apache.org/mina-based-application-architecture.html
* Server Architecture http://mina.apache.org/server-architecture.html
* Client Architecture http://mina.apache.org/client-architecture.html
其中幾個主要的元件如下:
I/O Service - 用來處理I/O流,對於Server端就是IOAcceptor的實現類接受Client端的連線請求,對於Client端就是IoConnector的實現類來建立到Server端的連線。
I/O Filter Chain - 用來過濾或轉化資料。對於Server端和Client端來說都是IoFilter介面的實現類,MINA自己內建了很多IoFilter介面的實現類。具體可以參考官方文件。
I/O Handler - 用來處理真正業務邏輯的類。對於Server端和Client端來說都是IoHandler介面的實現類,通常來說需要自己編寫。
由於Server端和Client端都是基於以上三個元件的,因此對於Server端和Client端程式設計來說就都有類似的程式碼結構。
對於Server端來說:
1. 建立I/O service - 這裡就是建立IOAcceptor類監聽埠。
2. 建立I/O Filter Chain - 這裡就是告訴使用那些IoFilter。
3. 建立I/O Handler - 自己的業務邏輯。
對於Client端來說:
1. 建立I/O service - 這裡就是建立IOConnector類來建立到Server端的連線。
2. 建立I/O Filter Chain - 這裡就是告訴使用那些IoFilter。
3. 建立I/O Handler - 自己的業務邏輯。
下面來通過一個例子看看MINA是怎樣工作的。由於大多數應用都是基於TCP/IP的應用,所以這裡也就不再說UDP/IP了。
這裡我使用了Maven來建立了一個簡單java應用程式,具體步驟請參Maven的官方手冊。這裡只是將我用到的maven配置檔案pom.xml列出,方便下面及後續文章使用。具體pom.xml檔案內容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.google.code.garbagecan.minastudy</groupId> <artifactId>minastudy</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>minastudy</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>org.apache.mina</groupId> <artifactId>mina-core</artifactId> <version>2.0.4</version> </dependency> <dependency> <groupId>org.apache.mina</groupId> <artifactId>mina-filter-compression</artifactId> <version>2.0.4</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.3.0</version> </dependency> </dependencies></project>
首先來看Server端的程式碼
package com.google.code.garbagecan.minastudy.sample1;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.service.IoHandlerAdapter;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.core.session.IoSession;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;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class MyServer { private static final Logger logger = LoggerFactory.getLogger(MyServer.class); public static void main(String[] args) { 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 IoHandlerAdapter() { @Override public void sessionCreated(IoSession session) throws Exception { } @Override public void sessionOpened(IoSession session) throws Exception { } @Override public void sessionClosed(IoSession session) throws Exception { } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { logger.error(cause.getMessage(), cause); session.close(true); } @Override public void messageReceived(IoSession session, Object message) throws Exception { logger.info("Received message " + message); session.write(message); } @Override public void messageSent(IoSession session, Object message) throws Exception { logger.info("Sent message " + message); } }); try { acceptor.bind(new InetSocketAddress(10000)); } catch (IOException ex) { logger.error(ex.getMessage(), ex); } }}
1. 首先建立I/O Service,這裡使用的是NioSocketAcceptor類來建立了一個IoAcceptor例項。
2. 建立I/O Filter Chain,這裡使用了兩個IoFilter,一個是LoggingFilter用來記錄日誌和列印事件訊息,另一個是ProtocolCodecFilter例項用來編碼資料,這裡其實就是將傳遞的資料編碼成文字。
3. 建立I/O Handler,不要害怕,看起來程式碼多,其實就是一個實現了IoHandler介面的子類,自己需要實現其中的一些方法,這裡方法比較多,但是我在這裡只實現了messageSent,messageReceived和exceptionCaught方法。
4. 最後就是讓IoAcceptor類例項繫結埠實現監聽。
下面看看Client端的程式碼
package com.google.code.garbagecan.minastudy.sample1;import java.net.InetSocketAddress;import java.nio.charset.Charset;import org.apache.mina.core.RuntimeIoException;import org.apache.mina.core.future.ConnectFuture;import org.apache.mina.core.service.IoConnector;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.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;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class MyClient { private static final Logger logger = LoggerFactory.getLogger(MyClient.class); public static void main(String[] args) { IoConnector connector = new NioSocketConnector(); connector.setConnectTimeoutMillis(10 * 1000); connector.getFilterChain().addLast("logger", new LoggingFilter()); connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8")))); connector.setHandler(new IoHandlerAdapter() { @Override public void sessionCreated(IoSession session) throws Exception { } @Override public void sessionOpened(IoSession session) throws Exception { for (int i = 0; i < 10; i++) { session.write("Hello user_" + i); } session.write("Bye"); } @Override public void sessionClosed(IoSession session) throws Exception { } @Override public void sessionIdle(IoSession session, IdleStatus status) throws Exception { } @Override public void exceptionCaught(IoSession session, Throwable cause) throws Exception { logger.error(cause.getMessage(), cause); session.close(true); } @Override public void messageReceived(IoSession session, Object message) throws Exception { logger.info("Received message " + message); if (message.toString().equalsIgnoreCase("Bye")) { session.close(true); } } @Override public void messageSent(IoSession session, Object message) throws Exception { logger.info("Sent message " + message); } }); IoSession session = null; try { ConnectFuture future = connector.connect(new InetSocketAddress("localhost", 10000)); future.awaitUninterruptibly(); session = future.getSession(); } catch (RuntimeIoException e) { logger.error(e.getMessage(), e); } session.getCloseFuture().awaitUninterruptibly(); connector.dispose(); }}
1. 首先建立I/O Service,這裡使用的是NioSocketConnector類來建立了一個IoConnector例項,並設定連線超時為10秒。
2. 建立I/O Filter Chain,和伺服器端同樣設定了兩個IoFilter,一個是LoggingFilter用來記錄日誌和列印事件訊息,另一個是ProtocolCodecFilter例項用來編碼資料,這裡其實就是將傳遞的資料編碼成文字。
3. 建立I/O Handler,也不要害怕,看起來程式碼多,其實也是一個實現了IoHandler介面的子類,並且自己實現了sessionOpened,messageSent,messageReceived和exceptionCaught方法。實現sessionOpened方法是為了在建立連線後向Server端傳送訊息。另外看一下messageReceived方法實現,在接收到伺服器端的訊息後關閉會話。從而可以使Client程式最終能夠退出。
4. 最後就是IoConnector例項類連線遠端的Server。
下面測試一下上面的程式,首先執行MyServer類,然後執行MyClient類,就可以分別在各自的終端上看到事件日誌以及傳送/接收的訊息了。