Apache Mina入门实例

一、mina是啥

ApacheMINA是一个网络应用程序框架,用来帮助用户简单地开发高性能和高可扩展性的网络应用程序。它提供了一个通过Java NIO在不同的传输例如TCP/IP和UDP/IP上抽象的事件驱动的异步API。(这是官方文档的翻译)

二、mina可以干啥

 现在要用mina写一个服务器和一个客户端通过TCP/IP协议通信的入门实例。

三、mina怎么做到

官方文档上有一幅图画得很好,是关于mina架构的,这里贴上来看一下:

基本上就是这样,一个请求过来,通过IoService,IoService新建一个Session,再通过一大堆的过滤器,最后到了一个处理器里面把业务逻辑处理完后再把结果返回去。

上代码~~~

1、服务器端代码:

MinaServer.java

public class MinaServer {

    private static final int Port = 8888;
    public void startMinaServer() {
        IoAcceptor ioAcceptor = new NioSocketAcceptor();
        System.out.println("server start to start!");

        //设置过滤器
        DefaultIoFilterChainBuilder defaultIoFilterChainBuilder = ioAcceptor.getFilterChain();
        defaultIoFilterChainBuilder.addLast("logger", new LoggingFilter());
        defaultIoFilterChainBuilder.addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
        System.out.println("config the filter chain finished!");

        //设置处理器
        ioAcceptor.setHandler(new FirstServerHandler());
        System.out.println("setting the handler finished!");

        //配置Session
        IoSessionConfig ioSessionConfig = ioAcceptor.getSessionConfig();
        ioSessionConfig.setReadBufferSize(2048);
        ioSessionConfig.setIdleTime(IdleStatus.BOTH_IDLE, 10);
        System.out.println("config the session finished!");

        //绑定端口
        try {
            ioAcceptor.bind(new InetSocketAddress(Port));
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("start finish!");
    }

    public static void main(String[] args) {
        MinaServer server = new MinaServer();
        server.startMinaServer();
    }
}
FirstServerHandler.java
public class FirstServerHandler extends IoHandlerAdapter{

    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        super.exceptionCaught(session, cause);
    }

    private static int message_count = 1;
    @Override
    public void messageReceived(IoSession session, Object message) {
        System.out.println("receive a message.");
        String string = message.toString();
        if(string.trim().toLowerCase().equals("quit")) {
            session.close(true);
            return;
        }
        System.out.println("received message:" + string);
        session.write("you are the no. " + message_count + " message!!!");
        message_count++;
        System.out.println("send back finished!!!");
    }

    @Override
    public void messageSent(IoSession session, Object message){
        System.out.println("message have been sent :" + message.toString());
        System.out.println();
    }

    @Override
    public void sessionClosed(IoSession session) {
        System.out.println("closed Session!");
    }

    @Override
    public void sessionCreated(IoSession session) {
        System.out.println("created session!");
    }

    @Override
    public void sessionIdle(IoSession session, IdleStatus status) {
        System.out.println("IDLE " + session.getIdleCount(status));
        System.out.println();
    }

    @Override
    public void sessionOpened(IoSession session) {
        System.out.println("opened session!");
        System.out.println();
    }
}

 2、客户端代码

MinaClient.java
public class MinaClient {

    private SocketConnector connector;
    private ConnectFuture future;
    private IoSession session;

    private String server_address = "127.0.0.1";
    private int server_port = 8888;

    public boolean connect() {

        connector = new NioSocketConnector();

        DefaultIoFilterChainBuilder defaultIoFilterChainBuilder = connector.getFilterChain();

        defaultIoFilterChainBuilder.addLast("logger", new LoggingFilter());
        defaultIoFilterChainBuilder.addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));

        connector.setHandler(new FirstClientHandler());

        future = connector.connect(new InetSocketAddress(server_address, server_port));
        future.awaitUninterruptibly();

        session = future.getSession();
        session.getConfig().setUseReadOperation(true);
        return future.isConnected();
    }

    public void sendMssageToServer(String message) {
        session.write(message);
    }

    public boolean close() {
        CloseFuture closeFuture = session.getCloseFuture();
        closeFuture.awaitUninterruptibly(1000);
        connector.dispose();
        return true;
    }

    public static void main(String[] args) {
        MinaClient client = new MinaClient();
        client.connect();

        String readLine = "";
        Scanner in = new Scanner(System.in);
        do {
            readLine = in.nextLine();
            client.sendMssageToServer(readLine);
        }while(!readLine.toLowerCase().equals("quit"));

        client.close();
    }
}
FirstClientHandler.java
public class FirstClientHandler extends IoHandlerAdapter {

    @Override
    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
        System.out.println("here got a exception!!!");
        super.exceptionCaught(session, cause);
    }

    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        System.out.println("received a message: " + message.toString());
        super.messageReceived(session, message);
    }

    @Override
    public void messageSent(IoSession session, Object message) throws Exception {
        System.out.println("sent a message: " + message.toString());
        super.messageSent(session, message);
    }

    @Override
    public void sessionCreated(IoSession session) throws Exception {
        System.out.println("session created!!!");
        super.sessionCreated(session);
    }
}

--------------------------------------------我是分割线------------------------------------------------------

3、服务器整合mina

SpringCodeFactory.java
public  class SpringCodeFactory implements ProtocolCodecFactory {

    private final TextLineEncoder encoder;
    private final TextLineDecoder decoder;
    /*final static char endchar = 0x1a;*/
    final static char endchar = 0x0d;
    public SpringCodeFactory() {
        this(Charset.forName("UTF-8"));
    }
    public SpringCodeFactory(Charset charset) {
        encoder = new TextLineEncoder(charset, LineDelimiter.UNIX);
        decoder = new TextLineDecoder(charset, LineDelimiter.AUTO);
    }
    @Override
    public ProtocolDecoder getDecoder(IoSession session) throws Exception {
        return decoder;
    }
    @Override
    public ProtocolEncoder getEncoder(IoSession session) throws Exception {
        return encoder;
    }
    public int getEncoderMaxLineLength() {
        return encoder.getMaxLineLength();
    }
    public void setEncoderMaxLineLength(int maxLineLength) {
        encoder.setMaxLineLength(maxLineLength);
    }
    public int getDecoderMaxLineLength() {
        return decoder.getMaxLineLength();
    }
    public void setDecoderMaxLineLength(int maxLineLength) {
        decoder.setMaxLineLength(maxLineLength);
    }

}

applicationContext-mina.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="java.net.SocketAddress" value="org.apache.mina.integration.beans.InetSocketAddressEditor">
                </entry>
            </map>
        </property>
    </bean>

    <bean id="executorFilter" class="org.apache.mina.filter.executor.ExecutorFilter" />
    <bean id="protocolCodecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
        <constructor-arg>
            <bean class="com.misuosi.mina.spring.SpringCodeFactory" />
        </constructor-arg>
    </bean>
    <bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter" />

    <bean id="filterChainBuilder" class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
        <property name="filters">
            <map>
                <entry key="executor" value-ref="executorFilter"></entry>
                <entry key="codec" value-ref="protocolCodecFilter"></entry>
                <entry key="logging" value-ref="loggingFilter"></entry>
            </map>
        </property>
    </bean>

    <bean id="firstServerHandler" class="com.misuosi.mina.server.FirstServerHandler" />

    <bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor"
          init-method="bind" destroy-method="unbind" >
        <property name="defaultLocalAddress" value=":8888" />
        <property name="handler" ref="firstServerHandler" />
        <property name="filterChainBuilder" ref="filterChainBuilder" />
        <property name="reuseAddress" value="true" />
    </bean>

    <bean id="sessionConfig" factory-bean="ioAcceptor" factory-method="getSessionConfig" >
        <property name="bothIdleTime" value="10"/>
        <property name="readBufferSize" value="2048" />
    </bean>
</beans>
SpringServer.java
public class SpringServer {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext ct = new ClassPathXmlApplicationContext("applicationContext-mina.xml");
    }
}

四、结果

1、服务器运行结果

2、客户端运行结果

 

五、参考文档

1、mina官方的用户指南

https://mina.apache.org/mina-project/userguide/user-guide-toc.html

2、Mina入门实例

http://www.cnblogs.com/juepei/p/3939119.html

3、Mina入门教程(二)----Spring4 集成Mina

http://www.w2bc.com/Article/5478

4、mina2.x与spring的集成开发

http://new-restart.iteye.com/blog/1286234

 

posted @ 2015-04-16 15:37  ICE_XUE  阅读(1965)  评论(2编辑  收藏  举报