mina2.X基于TCP/IP协议的开发示例

mina2.X基于TCP/IP协议的开发示例

 

 

 

 

------服务端

 

 

一、环境:

         (1)、java环境:jdk-1.6

         (2)、jar包:mina-core-2.0.4.jar           mina核心包

                               slf4j-api-1.6.1.jar                 日志接口包(只是接口,并未实现功能)

                               log4j-1.2.15.jar                  Apache的开源日志包

                               slf4j-log4j12-1.6.1.jar      slf4j调用log4j的日志接口实现包

         (3)、开发工具:eclipse3.7

 

二、mina2.X框架:

 

特点:mina2.X区别于mina1.X的最大特点是Nio非阻塞技术。每个线程负责一组数量不确定的用户群,并采不断的轮询用户,操作可操作的用户。之后,jdk1.4对这种方法进行了升级,采用异步多路复用技术,

避免了轮询的开销。

 

服务端相关类: IoAcceptor(服务套接字),IoFilter(消息过滤器),IoHandler(业务处理类)

 

三、项目介绍:

 

       本例模仿mina官方的TimeServer例子,当服务器收到客户端的消息时,返回当前的日期给客户端;当客户端发送字符串”quit”时,服务器断开连接(但是服务器并未关闭)。

       mina服务器端的开发大致遵循了以下步骤:

 

         (1)、创建服务器端监听  NioSocketAcceptor对象,相当于socket

 

   (2)、添加过滤器。

                   I、添加日志过滤器。没什么好说的,一般的服务器都要布置日志系统。

                   Ii、添加编码过滤器。TCP/IP协议簇传送的数据通过该过滤器解析成消息对象。

                   Iii、其他需要的过滤器。本例中不涉及其他过滤器。

 

         (3)、创建服务器的逻辑处理中心------一个继承了IoHandlerAdapter的Handler类。该类可以根据情况覆盖父类中的方法。本例将所有方法都覆盖,以观察这些方法何时触发。

   以下是Handler类的代码:

 

TimeServerHandler.java

 

package com.handaer.mina.server;
 
import java.util.Date;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
 
/**
 * 服务器逻辑处理类
 */
public classTimeServerHandler extends IoHandlerAdapter {
   // 应用中未被捕获的所有异常将被该方法捕获
   @Override
   public voidexceptionCaught(IoSession session, Throwable cause)
         throws Exception {
 
      cause.printStackTrace();
   }
 
   // 服务器接收到客户端返回消息时触发的方法,Object message就是客户端发送的消息
   @Override
   public voidmessageReceived(IoSession session, Object message)
         throws Exception {
      Stringtrim = message.toString().trim();
      System.out.println("messageReceived : "+ trim);
      // 定义:如果发送"quit"则连接断开
      if ("quit".equals(trim)) {
         session.close(true);
         return;
      }
 
      Datedate = newDate();
      session.write(date.toString());
      System.out.println("Message writen... ... : " + date.toString());
   }
 
   // 服务器向客户端发送消息时触发的方法.在本例中,messageSent的message将会是messageReceived中的date
   @Override
   public void messageSent(IoSessionsession, Object message) throws Exception {
      System.out.println("messageSent : "+ message);
   }
 
   // 与客户端连接中断时触发的方法
   @Override
   public void sessionClosed(IoSessionsession) throwsException {
 
      System.out.println("sessionClosed");
   }
 
   // 创建与客户端连接成功时触发的方法
   @Override
   public voidsessionCreated(IoSession session) throws Exception {
 
      System.out.println("sessionCreated");
   }
 
   // 连接处于空闲状态时触发的方法。空闲状态由在创建服务时SocketSessionConfig的setIdleTime方法设置,包括读取空闲,写入空闲,或者两者都空闲这三个状态
   @Override
   public void sessionIdle(IoSessionsession, IdleStatus status)
         throws Exception {
 
      System.out.println("sessionIdle : " +session.getIdleCount(status));
   }
 
   // 开启连接触发
   @Override
   public void sessionOpened(IoSessionsession) throwsException {
 
      System.out.println("sessionOpened");
   }
 
}
 


         服务还没有创建完成,继续创建服务。

 

         (4)、将刚才创建的任务(IoHandler)交给服务套接字(IoAcceptor)。(绑定handler)

 

         (5)、最后就是一些配置,具体参见代码。

package com.handaer.mina.server;
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.logging.Logger;
 
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
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.SocketAcceptor;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 
public classMinaTimeServer {
 
   private static SocketAcceptor acceptor;
   private staticDefaultIoFilterChainBuilder filter;
   private static SocketSessionConfig config;
   public static Logger logger = Logger.getLogger("TimeServer");
 
   /**
    * @Description: TODO(这里用一句话描述这个方法的作用)
    * @param args
    *           void 返回类型
    * @throws
    */
   public static void main(String[] args) {
      // 1、创建服务器端监听
      acceptor = new NioSocketAcceptor();
      // 2、添加日志过滤和编码过滤
      filter = acceptor.getFilterChain();
      filter.addLast("logger",newLoggingFilter());
      // ----编码过滤:将二进制或者协议相关数据转换成一个对象。TextLine工厂类可以处理基于文字的信息
      filter.addLast("codec",newProtocolCodecFilter(
            newTextLineCodecFactory(Charset.forName("GBK"))));
      // 3、绑定handler到acceptor
      acceptor.setHandler(new TimeServerHandler());
 
      // 4、设置socket属性
      // 获取socket的连接参数
      config = acceptor.getSessionConfig();
      // 设置socket的缓冲区大小为2M
      config.setReadBufferSize(2048);
      /**
       * @params IdleStatus arg0 :在未成为idle状态前应该关心的状态(READ_IDLE或者WRITE_IDLE)
       * @params IdleStatus arg1 : 变成IDLE状态所需要的时间(超时时间)
       *
       *        如果session持续idle的时间等于arg1时,将会触发handler中的sessionIdle方法
       */
      // 设置空闲状态持续时间:1、这里的状态可以自己设置成只为读取设置空闲状态持续时间,只为写入设置空闲状态等待时间,或者为两者都设置空闲状态等待时间。后面的时间是两次触发handler中的sessionIdel方法的间隔时间。
      config.setIdleTime(IdleStatus.BOTH_IDLE, 10);
      try {
         // 为服务器socket绑定端口
         acceptor.bind(new InetSocketAddress(7000));
         logger.info("服务已经启动... ...");
      }catch(IOException e) {
         logger.info("服务启动异常:");
         e.printStackTrace();
      }
 
   }
}


 

   至此,服务端已经完毕。跑起来

测试:

   1、使用telnet工具测试服务器。(之后还有客户端开发)

 

      打开cmd,输入telnet 127.0.0.17000 (确保telnet服务为本禁用且当前已经开启。)成功后,Eclipse控制台信息如:

 

   开启服务:

2013-9-4 11:21:42 com.handaer.mina.server.MinaTimeServermain
信息: 服务已经启动... ...
sessionCreated
sessionOpened


     

        

      输入字符:

messageReceived : 你好
Message writen... ... : Wed Sep 04 11:21:50 CST 2013
messageSent : Wed Sep 04 11:21:50 CST 2013
messageReceived : mina
Message writen... ... : Wed Sep 04 11:21:55 CST 2013
messageSent : Wed Sep 04 11:21:55 CST 2013


 

      关闭连接:

messageReceived : quit
sessionClosed


 

      关闭服务:点击控制台上面的红色按钮Teminate(如果服务未启动则该按钮是灰色)

 

  

2、使用浏览器测试(Http)。地址栏输入  : 127.0.0.1:7000 

2013-9-4 11:24:55 com.handaer.mina.server.MinaTimeServer main
信息: 服务已经启动... ...
sessionCreated
sessionOpened
sessionCreated
sessionOpened
messageReceived : GET / HTTP/1.1
Message writen... ... : Wed Sep 04 11:25:16 CST 2013
messageReceived : Host: 127.0.0.1:9123
Message writen... ... : Wed Sep 04 11:25:16 CST 2013
messageReceived : Connection: keep-alive
Message writen... ... : Wed Sep 04 11:25:16 CST 2013
messageReceived : Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Message writen... ... : Wed Sep 04 11:25:16 CST 2013
messageReceived : User-Agent: Mozilla/5.0 (Windows NT 6.1)AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Message writen... ... : Wed Sep 04 11:25:16 CST 2013
messageReceived : Accept-Encoding: gzip,deflate,sdch
Message writen... ... : Wed Sep 04 11:25:16 CST 2013
messageReceived : Accept-Language: zh-CN,zh;q=0.8
Message writen... ... : Wed Sep 04 11:25:16 CST 2013
messageReceived : Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Message writen... ... : Wed Sep 04 11:25:16 CST 2013
messageReceived :
Message writen... ... : Wed Sep 04 11:25:16 CST 2013
messageSent : Wed Sep 04 11:25:16 CST 2013
messageSent : Wed Sep 04 11:25:16 CST 2013
messageSent : Wed Sep 04 11:25:16 CST 2013
messageSent : Wed Sep 04 11:25:16 CST 2013
messageSent : Wed Sep 04 11:25:16 CST 2013
messageSent : Wed Sep 04 11:25:16 CST 2013
messageSent : Wed Sep 04 11:25:16 CST 2013
messageSent : Wed Sep 04 11:25:16 CST 2013
messageSent : Wed Sep 04 11:25:16 CST 2013
sessionClosed
sessionIdle :1

------客户端

 

与服务端基本一致,只是使用客户端的接口IoConnector。需要绑定ip和服务器指定的端口号

 

TimeClientHandler.java

 

package com.handaer.mina.client;
 
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
 
public classTimeClientHandler implements IoHandler {
 
   @Override
   public voidexceptionCaught(IoSession arg0, Throwable arg1)
         throws Exception {
      arg1.printStackTrace();
   }
 
   @Override
   public void messageReceived(IoSessionarg0, Object arg1) throws Exception {
      System.out.println("messageReceived : "+ arg1);
   }
 
   @Override
   public void messageSent(IoSessionarg0, Object arg1) throws Exception {
      System.out.println("messageSent : "+ arg1);
 
   }
 
   @Override
   public void sessionClosed(IoSessionarg0) throwsException {
      System.out.println("sessionClosed");
   }
 
   @Override
   public voidsessionCreated(IoSession arg0) throws Exception {
      System.out.println("sessionCreated");
   }
 
   @Override
   public void sessionIdle(IoSessionarg0, IdleStatus arg1) throws Exception {
      System.out.println("sessionIdle: "+ arg0.getIdleCount(arg1));
   }
 
   @Override
   public void sessionOpened(IoSessionarg0) throwsException {
      System.out.println("sessionOpened ");
   }
 
}
 

 

MinaTimeClient.java

 

 

package com.handaer.mina.client;
 
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
 
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
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;
 
public classMinaTimeClient {
 
   private static IoConnector connector;
   private staticDefaultIoFilterChainBuilder filterChain;
   private static ConnectFuture future;
   private static IoSession session;
 
   public static void main(String[] args) {
      // 1、创建客户端通讯串口
      connector = new NioSocketConnector();
      // 2、添加日志过滤和编码过滤
      filterChain = connector.getFilterChain();
      filterChain.addLast("loggor",newLoggingFilter());
      filterChain.addLast("codec",newProtocolCodecFilter(
            newTextLineCodecFactory(Charset.forName("GBK"))));
      // 3、绑定handler
      connector.setHandler(new TimeClientHandler());
      // 4、创建连接
      try {
         future = connector
                .connect(new InetSocketAddress("127.0.0.1",7000));
         future.awaitUninterruptibly();//
         session = future.getSession();
         // 向服务器发送消息
         session.write("你好mina");
         session.write("quit");
      }catch(Exception e) {
         // TODO: handle exception
      }finally{
         Logger.getLogger("logger").info("finally");
         // 从客户端关闭连接方法。(推荐从服务器关闭连接)
         session.getCloseFuture().awaitUninterruptibly();// 等待连接断开
         connector.dispose();
         // session.write("quit"); //服务器定义如果收到"quit"则关闭连接,推荐的关闭方式
 
      }
 
   }
 
}

------log4j.properties日志配置文件

 

如果控制台出现如下警告,原因是log4j.propertis文件错误或者不存在:

log4j:WARN No appenders could be found for logger(org.apache.mina.filter.logging.LoggingFilter).
log4j:WARNPlease initialize the log4j system properly.


在服务器和客户端都有配置log4j.propertis:

  在项目的src目录下创建log4j.propertis,其内容可以根据需要修改。

  本项目内内容如下:

 

                   #Loggers
#log4j.rootLogger=info,file,console
log4j.rootLogger=info,file
 
#Appenders
#console
#log4j.appender.console=org.apache.log4j.ConsoleAppender;
#log4j.appender.console.layout=org.log4j.SimpleLayout
 
#file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=f:/NetBeans/logtest.log
log4j.appender.file.MaxFileSize=20KB
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d {yyyy-MM-ddHH:mm:ss,SSSS}%c,%M,%F,%L%p - %m%n
 


  点击下载源码

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值