• 【Andorid开发框架学习】之Mina开发之客户端开发


      

        昨天我们讲到了Mina的基本知识点。如果还有不懂得同学可以看一下我昨天的博客。http://www.cnblogs.com/getherBlog/p/3934927.html今天我着重来讲一下基于Mina的客户端的开发(代码均在最后链接地址中,欢迎下载)。

       一、首先看一下,我的客户端的代码图片:

           客户端代码我是在Eclipse下写的。

       二、客户端的整体思路:

        • 首先,产生一个socket连接对象,用于连接到服务器;
        • 然后,对这个连接添加我们的I/O过滤器(SSL加密、日志过滤器、编码过滤器等,这里注意,如果添加SSL过滤器,那么一定要第一个添加,否则无法对数据加密);
        • 接下来,为连接设置I/O处理器,顾名思义就是处理接收到的消息(这里我们只能设置一个处理器,如果有设置多个,那么默认进入到最后一个I/O处理器中进行处理);
        • 最后,连接到通过IP和端口号连接到服务器;保存连接的获取到的session,如果需要发送消息,我们就可以对session进行操作。

     

       三、正式编码

          这里我展示几个比较重要的类来详细说明一下:

        • MinaClient.Java
          package com.example.mina.server;
          
          import java.net.InetSocketAddress;
          
          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.logging.LoggingFilter;
          import org.apache.mina.filter.ssl.SslFilter;
          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;
          import com.example.mina.ssl.SSLContextGenerator;
          
          /**
           * <pre>
           * Project Name:MinaClient
           * Package:com.example.mina.server
           * FileName:MinaClient.java
           * Purpose:客户端
           * Create Time: 2014-8-19 下午4:36:55
           * Create Specification:
           * Modified Time:
           * Modified by:
           * Modified Specification:
           * Version: 1.0
           * </pre>
           * 
           * @author myp
           */
          public class MinaClient {
          
              private SocketConnector connector;
              private ConnectFuture future;
              private IoSession session;
          
              public boolean connect() {
                  /*
                   * 1.创建一个socket连接,连接到服务器
                   */
                  connector = new NioSocketConnector();
          
                  /*
                   * 获取过滤器链,用于添加过滤器
                   */
                  DefaultIoFilterChainBuilder chain = connector.getFilterChain();
          
                  /*
                   * 2.为连接添加过滤器,SSL、日志、编码过滤器
                   */
                  // SSLContextGenerator是我们自己写的一个SSL上下文产生器,稍后会讲到
                  SslFilter sslFilter = new SslFilter(
                          new SSLContextGenerator().getSslContext());
                  // 设置为客户端模式
                  sslFilter.setUseClientMode(true);
                  // a.ssl过滤器,这个一定要第一个添加,否则数据不会进行加密
                  chain.addFirst("sslFilter", sslFilter);
          
                  // b.添加日志过滤器
                  chain.addLast("logger", new LoggingFilter());
          
                  // c.添加字符的编码过滤器
                  chain.addLast("codec", new ProtocolCodecFilter(new CharsetFactory()));
          
                  /*
                   * 3.设置消息处理器,用于处理接收到的消息
                   */
                  connector.setHandler(new MsgHanler());
          
                  /*
                   * 4.根据IP和端口号连接到服务器
                   */
                  future = connector.connect(new InetSocketAddress("192.168.1.12", 3456));
                  // 等待连接创建完成
                  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;
              }
          }
          View Code

          MinaClient就是按照第二步当中的流程走过来的;所以编程的时候最主要的是整体的思路,思路明白了那么编程就会变得异常效率。

        • SSLContextGenerator.Java
          package com.example.mina.ssl;
          
          import java.io.File;
          import java.security.KeyStore;
          
          import javax.net.ssl.SSLContext;
          
          import org.apache.mina.filter.ssl.KeyStoreFactory;
          import org.apache.mina.filter.ssl.SslContextFactory;
          
          /**
           * <pre>
           * Project Name:SSLContextGenerator
           * Package:com.example.mina.ssl
           * FileName:SSLContextGenerator.java
           * Purpose:客户端
           * Create Time: 2014-8-19 下午4:41:55
           * Create Specification:
           * Modified Time:
           * Modified by:
           * Modified Specification:
           * Version: 1.0
           * </pre>
           * 
           * @author myp
           */
          public class SSLContextGenerator {
          
              /**
               * 这个方法,通过keystore和truststore文件返回一个SSLContext对象
               * 
               * @return
               */
              public SSLContext getSslContext() {
                  SSLContext sslContext = null;
                  try {
                      /*
                       * 提供keystore的存放目录,读取keystore的文件内容
                       */
                      File keyStoreFile = new File("C:/Users/Administrator/keystore.jks");
          
                      /*
                       * 提供truststore的存放目录,读取truststore的文件内容
                       */
                      File trustStoreFile = new File(
                              "C:/Users/Administrator/truststore.jks");
          
                      if (keyStoreFile.exists() && trustStoreFile.exists()) {
                          final KeyStoreFactory keyStoreFactory = new KeyStoreFactory();
                          System.out.println("Url is: " + keyStoreFile.getAbsolutePath());
                          keyStoreFactory.setDataFile(keyStoreFile);
          
                          /*
                           * 这个是当初我们使用keytool创建keystore和truststore文件的密码,也是上次让你们一定要记住密码的原因了
                           */
                          keyStoreFactory.setPassword("134426myp");
          
                          final KeyStoreFactory trustStoreFactory = new KeyStoreFactory();
                          trustStoreFactory.setDataFile(trustStoreFile);
                          trustStoreFactory.setPassword("134426myp");
          
                          final SslContextFactory sslContextFactory = new SslContextFactory();
                          final KeyStore keyStore = keyStoreFactory.newInstance();
                          sslContextFactory.setKeyManagerFactoryKeyStore(keyStore);
          
                          final KeyStore trustStore = trustStoreFactory.newInstance();
                          sslContextFactory.setTrustManagerFactoryKeyStore(trustStore);
                          sslContextFactory
                                  .setKeyManagerFactoryKeyStorePassword("134426myp");
                          sslContext = sslContextFactory.newInstance();
                          System.out.println("SSL provider is: "
                                  + sslContext.getProvider());
                      } else {
                          System.out
                                  .println("Keystore or Truststore file does not exist");
                      }
                  } catch (Exception ex) {
                      ex.printStackTrace();
                  }
                  return sslContext;
              }
          }
          View Code

          如果不知道如何创建keystore和truststore文件的话,请查看我的这篇博客:http://www.cnblogs.com/getherBlog/p/3930317.html

     

        • MsgHandler.Java
          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;
          
          /**
           * <pre>
           * Project Name:MsgHanler
           * Package:com.example.mina.handler
           * FileName:MsgHanler.java
           * Purpose:I/O消息处理器,从这里我们就可以看出Mina是事件驱动的
           * Create Time: 2014-8-19 下午4:39:55
           * Create Specification:
           * Modified Time:
           * Modified by:
           * Modified Specification:
           * Version: 1.0
           * </pre>
           * 
           * @author myp
           */
          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);
              }
          }
          View Code

          基本上我们最主要的就是对在I/O处理器这里对收到的消息进行处理,也是编程的核心所在!

       四、注意事项

        1. 关于Mina的日志过滤器误区,不知道会不会有同学有这样的认为,我们的log4j-1.2.17.jar就是我们的mina的日志,那么我告诉你你理解错了,log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输出。Mina的日志过滤器是使用了slf4j-log4j12-1.7.6.jar、slf4j-api-1.7.6.jar包;
        2. log4j的配置问题,如果需要使用Apache的开源项目,我们需要配置log4j.properties文件,下面是他的代码;
          log4j.rootCategory=INFO, stdout , R   
             
          log4j.appender.stdout=org.apache.log4j.ConsoleAppender   
          log4j.appender.stdout.layout=org.apache.log4j.PatternLayout   
          log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n   
              
          log4j.appender.R=org.apache.log4j.DailyRollingFileAppender  
          log4j.appender.R.File=D:\Mina\logs\client.log   
          log4j.appender.R.layout=org.apache.log4j.PatternLayout   
          1log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n   
             
          log4j.logger.com.neusoft=DEBUG   
          log4j.logger.com.opensymphony.oscache=ERROR   
          log4j.logger.net.sf.navigator=ERROR   
          log4j.logger.org.apache.commons=ERROR   
          log4j.logger.org.apache.struts=WARN   
          log4j.logger.org.displaytag=ERROR   
          log4j.logger.org.springframework=DEBUG   
          log4j.logger.com.ibatis.db=WARN   
          log4j.logger.org.apache.velocity=FATAL   
             
          log4j.logger.com.canoo.webtest=WARN   
             
          log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN   
          log4j.logger.org.hibernate=DEBUG   
          log4j.logger.org.logicalcobwebs=WARN  
          
          log4j.rootCategory=INFO, stdout , R
          
          log4j.appender.stdout=org.apache.log4j.ConsoleAppender
          log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
          log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
           
          log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
          log4j.appender.R.File=D:\Tomcat 5.5\logs\qc.log
          log4j.appender.R.layout=org.apache.log4j.PatternLayout
          1log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n
          
          log4j.logger.com.neusoft=DEBUG
          log4j.logger.com.opensymphony.oscache=ERROR
          log4j.logger.net.sf.navigator=ERROR
          log4j.logger.org.apache.commons=ERROR
          log4j.logger.org.apache.struts=WARN
          log4j.logger.org.displaytag=ERROR
          log4j.logger.org.springframework=DEBUG
          log4j.logger.com.ibatis.db=WARN
          log4j.logger.org.apache.velocity=FATAL
          
          log4j.logger.com.canoo.webtest=WARN
          
          log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
          log4j.logger.org.hibernate=DEBUG
          log4j.logger.org.logicalcobwebs=WARN
          View Code

          我们可以再这里设置我们的日志输出目录:log4j.appender.R.File=D:\Mina\logs\client.log   

             3. SSL加密中,如果不知道如何使用keystore生成keystore和truststore文件,可以查看这篇博客:http://www.cnblogs.com/getherBlog/p/3930317.html

             4. 在添加过滤器的时候,处理的顺序是按照添加过滤器的顺序;

             5. Mina在使用过滤器的时候,只要在需要的地方添加就可以了,不一定是服务器、客户端都要添加的。就是说,服务器、客户端编程的时候服务器有这个过滤器,客户端可以有也可以没有。

            

      

       五、Mina客户端源码下载

            点我下载

            下载后导入到Eclipse当中,将com.example.mina.server包下面的MinaClient类中的下面代码注释掉,然后就可以正常运行了!原因是你本地不存在keystore和truststore文件,如果需要生成请看注意事项中第三条。

        SslFilter sslFilter = new SslFilter(
                    new SSLContextGenerator().getSslContext());
            sslFilter.setUseClientMode(true);
            chain.addFirst("sslFilter", sslFilter);

            

         

       下一篇应该是Mina的服务器的开发,欢迎订阅!我的CSDN地址:http://blog.csdn.net/u010049692/article/details/38847129

  • 相关阅读:
    php怎么实现多态?
    php怎么识别真实ip
    php析构函数什么时候调用?
    php解析xml的几种方式
    thinkPHP5框架路由常用知识点汇总
    用Python打造了一个渗透测试暴力探测器
    修复wecenter移动版description首页描述一样问题
    寒假小软件开发记录02--布局
    寒假小软件开发记录01--确定方向和素材准备
    大二上学期个人总结
  • 原文地址:https://www.cnblogs.com/getherBlog/p/3937196.html
Copyright © 2020-2023  润新知