zoukankan      html  css  js  c++  java
  • Mina入门实例(一)

    mina现在用的很多了,之前也有用到,但是毕竟不熟悉,于是查了一些资料,做了一些总结。看代码是最直观的,比什么长篇大论都要好。不过其中重要的理论,也要理解下。

    首先是环境,程序运行需要几个包,这里用maven比较方便。

    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/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>MyMinaServer</groupId>
      <artifactId>mina</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>mina</name>
      <url>http://maven.apache.org</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
    
      <dependencies>
          <dependency>  
                <groupId>org.apache.mina</groupId>  
                <artifactId>mina-core</artifactId>  
                <version>2.0.4</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.slf4j</groupId>  
                <artifactId>jcl-over-slf4j</artifactId>  
                <version>1.6.1</version>  
            </dependency>  
      
            <dependency>  
                <groupId>org.slf4j</groupId>  
                <artifactId>slf4j-nop</artifactId>  
                <version>1.6.1</version>  
            </dependency>  
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    </project>

    然后就可以写代码了。

    ---------------------------------------------------------- 分割线 -----------------------------------------------------------------------------------------

    一,简单的客户端和服务端程序

    服务端程序:

    package MyMinaServer.mina;
    
    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 MainServer {
        private static final int Port=8888;
        public static void main(String[] args) {
            IoAcceptor ioAcceptor=new NioSocketAcceptor();
            System.out.println("begin server....");
            ioAcceptor.getFilterChain().addLast("logger", new LoggingFilter());
            ioAcceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
            ioAcceptor.setHandler(new HelloWorldHandler());
            ioAcceptor.getSessionConfig().setReadBufferSize(2048);
            ioAcceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
            try {
                ioAcceptor.bind(new InetSocketAddress(Port));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    服务端,创建连接,然后这里注册了几个过滤链,这里简单写了需要的两个,到后面的内容中还可以加入一个加密的ssl链。

    其中重要的是setHandler这个,在这个里面,我们可以定义自己的handler,然后做自己的业务。下面有这个handler的简单代码。

    最后设置session的缓冲,和idle(空闲处理)的设定,再为此连接绑定一个端口。

    其中需要注意的是,在服务端和客户端的代码里面,如果要传递string信息,codec编码过滤器中,要这么写:new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8")))。否则报错。

    业务处理的handler:

    package MyMinaServer.mina;
    
    import org.apache.mina.core.service.IoHandlerAdapter;
    import org.apache.mina.core.session.IdleStatus;
    import org.apache.mina.core.session.IoSession;
    
    public class HelloWorldHandler extends IoHandlerAdapter{
    
        @Override
        public void exceptionCaught(IoSession session, Throwable cause)
                throws Exception {
            // TODO Auto-generated method stub
            super.exceptionCaught(session, cause);
        }
    
        @Override
        public void messageReceived(IoSession session, Object message)
                throws Exception {
            // TODO Auto-generated method stub
            String string=message.toString();
            if (string.trim().equalsIgnoreCase("quit")) {
                session.close(true);
                return;
            }
            System.out.println("recevied message:"+string);
            String reply=" hi, i am server";
            session.write(reply);
            System.out.println("message have been written");
        }
    
        @Override
        public void messageSent(IoSession session, Object message) throws Exception {
            // TODO Auto-generated method stub
            System.out.println("message have been sent");
        }
    
        @Override
        public void sessionClosed(IoSession session) throws Exception {
            // TODO Auto-generated method stub
            System.out.println("closed session");
        }
    
        @Override
        public void sessionCreated(IoSession session) throws Exception {
            // TODO Auto-generated method stub
            System.out.println("session created");
        }
    
        @Override
        public void sessionIdle(IoSession session, IdleStatus status)
                throws Exception {
            // TODO Auto-generated method stub
            System.out.println("IDLE "+session.getIdleCount(status));
        }
    
        @Override
        public void sessionOpened(IoSession session) throws Exception {
            // TODO Auto-generated method stub
            System.out.println("session opened");
        }
    
    }

    这里的每个方法,算是事件。在每个事件中,我们可以定义自己的处理。在前面的《AndroidPn源码分析(一)》这篇文章中,笔者曾写过他们的每个事件代表的含义,不过从字面意思也很好理解。

    这里主要是对接受到信息的处理,如果不是收到quit字符,则返回给客户端一句 hi,i am server。

    服务端暂时到此,以下是客户端。

    package com.example.mina.server;
    
    import java.net.InetSocketAddress;
    import java.nio.charset.Charset;
    
    import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
    import org.apache.mina.core.future.CloseFuture;
    import org.apache.mina.core.future.ConnectFuture;
    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.SocketConnector;
    import org.apache.mina.transport.socket.nio.NioSocketConnector;
    
    import com.example.mina.charset.CharsetFactory;
    import com.example.mina.hanlder.MsgHanler;public class MinaClient {
    
        private SocketConnector connector;
        private ConnectFuture future;
        private IoSession session;
    
        public boolean connect() {
            /*
             * 1.创建一个socket连接,连接到服务器
             */
            connector = new NioSocketConnector();
    
            /*
             * 获取过滤器链,用于添加过滤器
             */
            DefaultIoFilterChainBuilder chain = connector.getFilterChain();
    
            // b.添加日志过滤器
            chain.addLast("logger", new LoggingFilter());
    
            // c.添加字符的编码过滤器
            chain.addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
    
            /*
             * 3.设置消息处理器,用于处理接收到的消息
             */
            connector.setHandler(new MsgHanler());
    
            /*
             * 4.根据IP和端口号连接到服务器
             */
            future = connector.connect(new InetSocketAddress("127.0.0.1", 8888));
            // 等待连接创建完成
            future.awaitUninterruptibly();
    
            /*
             * 5.获取session对象,通过session可以向服务器发送消息;
             */
            session = future.getSession();
            session.getConfig().setUseReadOperation(true);
            return future.isConnected();
        }
    
        /**
         * 往服务器发送消息
         * 
         * @param message
         */
        public void sendMsg2Server(String message) {
            session.write(message);
        }
    
        /**
         * 关闭与服务器的连接
         * 
         * @return
         */
        public boolean close() {
            CloseFuture future = session.getCloseFuture();
            future.awaitUninterruptibly(1000);
            connector.dispose();
            return true;
        }
    }

    然后同样是一个客户端的handler,和server的很像:

    package com.example.mina.hanlder;
    
    import org.apache.mina.core.service.IoHandlerAdapter;
    import org.apache.mina.core.session.IoSession;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class MsgHanler extends IoHandlerAdapter {
        private static final Logger log = LoggerFactory.getLogger(MsgHanler.class);
    
        @Override
        public void exceptionCaught(IoSession session, Throwable cause)
                throws Exception {
            // 出现异常
            log.error("--------exception--------");
            super.exceptionCaught(session, cause);
        }
    
        @Override
        public void messageReceived(IoSession session, Object message)
                throws Exception {
            // 从服务器中接收到消息后的处理
            log.info("--------msg receive--------");
            log.info("Message:{}" + message.toString());
            super.messageReceived(session, message);
        }
    
        @Override
        public void messageSent(IoSession session, Object message) throws Exception {
            // 往服务器中发送消息
            log.info("--------msg sent--------");
            super.messageSent(session, message);
        }
    
        @Override
        public void sessionCreated(IoSession session) throws Exception {
            // 当session被创建的时候调用
            log.info("--------session create--------");
            super.sessionCreated(session);
        }
    }

    写一个入口方法:

    package com.example.mina.server;
    
    public class Main {
    
        public static void main(String[] args) {
            MinaClient client=new MinaClient();
            client.connect();
            client.sendMsg2Server("message from cilent");
        }
    }

    这样,客户端就可以工作了。

    先启动服务端,然后启动客户端,就可以看到在两个控制台中,分别有交互信息。

    服务端:

    begin server....
    session created
    session opened
    recevied message:message from cilent
    message have been written
    message have been sent

    客户端:

    [QC] INFO [NioProcessor-2] org.apache.mina.filter.logging.LoggingFilter.log(186) | CREATED
    [QC] INFO [NioProcessor-2] com.example.mina.hanlder.MsgHanler.sessionCreated(54) | --------session create--------
    [QC] INFO [NioProcessor-2] org.apache.mina.filter.logging.LoggingFilter.log(186) | OPENED
    [QC] INFO [NioProcessor-2] org.apache.mina.filter.logging.LoggingFilter.log(157) | SENT: HeapBuffer[pos=0 lim=0 cap=0: empty]
    [QC] INFO [NioProcessor-2] com.example.mina.hanlder.MsgHanler.messageSent(47) | --------msg sent--------
    [QC] INFO [NioProcessor-2] org.apache.mina.filter.logging.LoggingFilter.log(157) | RECEIVED: HeapBuffer[pos=0 lim=17 cap=2048: 20 68 69 2C 20 69 20 61 6D 20 73 65 72 76 65 72...]
    [QC] INFO [NioProcessor-2] com.example.mina.hanlder.MsgHanler.messageReceived(39) | --------msg receive--------
    [QC] INFO [NioProcessor-2] com.example.mina.hanlder.MsgHanler.messageReceived(40) | Message:{} hi, i am server

    客户端因为用了log4j,打印比较多信息。

    到此,这个例子就完成了。

  • 相关阅读:
    [好文翻译]保卫你的日历
    如何使用PowerShell修改Host文件
    如何使用PowerShell修改注册表
    MSDN文章纠错Automating Microsoft SharePoint 2010 with Windows PowerShell 2.0 (book excerpt)
    如何在PowerShell中得到一个对象的所有属性名和方法名呢?
    Service Object Model
    记录一个问题的解决方法
    STSADM Sync 命令里的 – Ignoreisactive 标志位
    Javascript实现图片位置控制(鼠标拖拽 + 键盘方向键移动)源码分享
    从零开始学习jQuery (六) AJAX快餐【转】
  • 原文地址:https://www.cnblogs.com/juepei/p/3939119.html
Copyright © 2011-2022 走看看