【Apache Mina2.0开发之一】搭建Apache Mina框架并实现Server与Client端消息传递

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

Hibernate系列学习阶段到此结束了,那么紧接着进入Apache Mina的开发学习,很多童鞋在微薄和QQ中疑问Himi为什么突然脱离游戏开发了,嘿嘿,其实可能更多的童鞋已经看出来了,Himi在偏向服务器Server端开发了,Hibernate、MySQL等都是为了Server端Mina开发而做的铺垫,当前的Apache Mina才是Himi真正的目的。哈哈。Himi的技术目标是“一个人能做出一个网游~”,OK.不多说其他的了,开始Himi的Apache mina开发之旅吧。

对于Apache Mina不太连接的童鞋,请移步到如下百度百科连接进行学习了解:

http://baike.baidu.com/view/2668084.htm 

首先建立一个new project(Server端),这里Himi使用IDE是 eclipse;

OK,首先我们这里先配置下环境:对于Mina的日志输出使用的是slf4j,对于slf4j在开发Hibernate的时候已经很熟悉了,不需要再介绍了。另外一方面就是加入mina的core核心jar包;

1. mina-core.jar         2. slf4j-api.jar         3.slf4j-simple.jar

然后我们首先创建两个类:

HimiObject.java

 


  
  
  1. /** 
  2.  * @author Himi 
  3.  */ 
  4.  
  5. import java.io.Serializable; 
  6.  
  7. public class HimiObject implements Serializable{ 
  8.  
  9.     public HimiObject(int id,String name){ 
  10.         this.id=id; 
  11.         this.name=name; 
  12.     } 
  13.  
  14.     private int id; 
  15.  
  16.     private String name; 
  17.  
  18.     public int getId() { 
  19.         return id; 
  20.     } 
  21.     public void setId(int id) { 
  22.         this.id = id; 
  23.     } 
  24.     public String getName() { 
  25.         return name; 
  26.     } 
  27.     public void setName(String name) { 
  28.         this.name = name; 
  29.     } 
  30.  

这个类是个消息Object,它用于server与client端的交互的数据,它需要序列化,所以我们使用Serializable接口;至于在mina框架中起到什么作用这个后续来说;

 

ClientMinaServerHanlder.java

 


  
  
  1. /** 
  2.  * @author Himi 
  3.  */ 
  4.  
  5. import org.apache.mina.core.service.IoHandlerAdapter; 
  6. import org.apache.mina.core.session.IdleStatus; 
  7. import org.apache.mina.core.session.IoSession; 
  8.  
  9. public class ClientMinaServerHanlder extends IoHandlerAdapter { 
  10.  
  11.     private int count = 0
  12.  
  13.     // 当一个新客户端连接后触发此方法. 
  14.     public void sessionCreated(IoSession session) { 
  15.         System.out.println("新客户端连接"); 
  16.     } 
  17.  
  18.     // 当一个客端端连结进入时 @Override 
  19.     public void sessionOpened(IoSession session) throws Exception { 
  20.         count++; 
  21.         System.out.println("第 " + count + " 个 client 登陆!address: : " 
  22.                 + session.getRemoteAddress()); 
  23.  
  24.     } 
  25.  
  26.     // 当客户端发送的消息到达时: 
  27.     @Override 
  28.     public void messageReceived(IoSession session, Object message) 
  29.             throws Exception { 
  30.         // // 我们己设定了服务器解析消息的规则是一行一行读取,这里就可转为String: 
  31.         // String s = (String) message; 
  32.         // // Write the received data back to remote peer 
  33.         // System.out.println("收到客户机发来的消息: " + s); 
  34.         // // 测试将消息回送给客户端 session.write(s+count); count++; 
  35.  
  36.         HimiObject ho = (HimiObject) message; 
  37.         System.out.println(ho.getName()); 
  38.  
  39.         ho.setName("serverHimi"); 
  40.         session.write(ho); 
  41.  
  42.     } 
  43.  
  44.     // 当信息已经传送给客户端后触发此方法. 
  45.     @Override 
  46.     public void messageSent(IoSession session, Object message) { 
  47.         System.out.println("信息已经传送给客户端"); 
  48.  
  49.     } 
  50.  
  51.     // 当一个客户端关闭时 
  52.     @Override 
  53.     public void sessionClosed(IoSession session) { 
  54.         System.out.println("one Clinet Disconnect !"); 
  55.     } 
  56.  
  57.     // 当连接空闲时触发此方法. 
  58.     @Override 
  59.     public void sessionIdle(IoSession session, IdleStatus status) { 
  60.         System.out.println("连接空闲"); 
  61.     } 
  62.  
  63.     // 当接口中其他方法抛出异常未被捕获时触发此方法 
  64.     @Override 
  65.     public void exceptionCaught(IoSession session, Throwable cause) { 
  66.         System.out.println("其他方法抛出异常"); 
  67.     } 
  68.  

本类主要是继承IoHandlerAdapter并且重写其类的一些函数,至于每个函数的作用Himi都已经在代码中加以注视;本类的作用:

此类是用以处理消息的也可说是个消息处理器,当客户端有消息传给server端的时候,或者server端传递给Client端的时候(Client端也会有个消息处理器)都会通过消息处理器进行处理。

OK,下面我们来书写server端的main函数类:

 


  
  
  1. /** 
  2.  * @author Himi 
  3.  */ 
  4.  
  5. import java.io.IOException; 
  6. import java.net.InetSocketAddress; 
  7.  
  8. import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; 
  9. import org.apache.mina.filter.codec.ProtocolCodecFilter; 
  10. import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory; 
  11. import org.apache.mina.transport.socket.SocketAcceptor; 
  12. import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 
  13.  
  14. public class MinaServer { 
  15.  
  16.     /** 
  17.      * @param args 
  18.      */ 
  19.  
  20.     public static void main(String[] args) { 
  21.         //创建一个非阻塞的server端Socket ,用NIO 
  22.         SocketAcceptor acceptor = new NioSocketAcceptor(); 
  23.  
  24.         /*---------接收字符串---------*/ 
  25. //      //创建一个接收数据过滤器 
  26. //      DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); 
  27. //      //设定过滤器一行行(/r/n)的读取数据 
  28. //      chain.addLast("mychin", new ProtocolCodecFilter(new TextLineCodecFactory()   )); 
  29.         /*---------接收对象---------*/ 
  30.         //创建接收数据的过滤器 
  31.         DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); 
  32.         //设定这个过滤器将以对象为单位读取数据 
  33.         ProtocolCodecFilter filter= new ProtocolCodecFilter(new ObjectSerializationCodecFactory()); 
  34.         chain.addLast("objectFilter",filter); 
  35.  
  36.         //设定服务器消息处理器 
  37.         acceptor.setHandler(new ClientMinaServerHanlder()); 
  38.         //服务器绑定的端口 
  39.         int bindPort = 9988
  40.         //绑定端口,启动服务器 
  41.         try { 
  42.             acceptor.bind(new InetSocketAddress(bindPort)); 
  43.         } catch (IOException e) { 
  44.             System.out.println("Mina Server start for error!"+bindPort); 
  45.             e.printStackTrace(); 
  46.         } 
  47.         System.out.println("Mina Server run done! on port:"+bindPort); 
  48.     } 

IoService 是负责底层通讯接入,而 IoHandler 是负责业务处理的。那么 MINA 架构图中的 IoFilter 作何用途呢?答案是你想作何用途都可以。但是有一个用途却是必须的,那就是作为 IoService 和 IoHandler 之间的桥梁。IoHandler 接口中最重要的一个方法是 messageReceived,这个方法的第二个参数是一个 Object 型的消息,总所周知,Object 是所有 Java 对象的基础,那到底谁来决定这个消息到底是什么类型呢?这个取决于我们后面设定的过滤器!  

对于在mina中建立一个server,步骤如下:

 1. 建立一个SockerAcceptor ,除了启动server之外它还可以为我们可以生成过滤器DefaultIoFilterChainBuilder、设置消息处理器等功能;

        2.设置过滤器

        3. 设置消息处理器

其实很容易不是么? 哈哈;

OK,这里多说一些:

对于消息处理器 DefaultIoFilterChainBuilder,它的作用是用于设定收发的形式,例如:

 


  
  
  1. //创建一个接收数据过滤器 
  2.         DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); 
  3.         //设定过滤器一行行(/r/n)的读取数据 
  4.         chain.addLast("mychin"new ProtocolCodecFilter(new TextLineCodecFactory()   )); 

这样设置一个过滤器作用是将来自客户端输入的信息转换成一行行的文本后传递给 IoHandler,因此我们可以在 messageReceived 中直接将 msg 对象强制转换成 String 对象。

ps.而如果我们不提供任何过滤器的话,那么在 messageReceived 方法中的第二个参数类型就是一个 byte 的缓冲区,对应的类是 org.apache.mina.common.ByteBuffer。虽然你也可以将解析客户端信息放在 IoHandler 中来做,但这并不是推荐的做法,使原来清晰的模型又模糊起来,变得 IoHandler 不只是业务处理,还得充当协议解析的任务。

mina自身带有一些常用的过滤器,例如LoggingFilter(日志记录)、BlackListFilter(黑名单过滤)、CompressionFilter(压缩)、SSLFilter(SSL加密)等。

当我们设置如下:

 


  
  
  1. //创建接收数据的过滤器 
  2.         DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); 
  3.         //设定这个过滤器将以对象为单位读取数据 
  4.         ProtocolCodecFilter filter= new ProtocolCodecFilter(new ObjectSerializationCodecFactory()); 
  5.         chain.addLast("objectFilter",filter); 

这样以来我们server可以收发Object对象啦;

?
1
acceptor.setHandler( new  ClientMinaServerHanlder());

这里是设置消息处理器,绑定在我们的ClientMinaServerHanlder类上,其实mina对于收发处理已经完全交给开发者来进行处理,所以至于在消息处理器如何编写和处理就放任不会管了;

OK,现在我们可以run一下启动server端了;

当然我们现在也可以来测试了,当前我们还没有书写Client端的代码,所以我们使用terminal终端进行测试,OK,打开你的terminal

然后输入  telnet localhost 9988

观察服务器打印:

OK,没有任何问题;但是这时候大家不要在终端书写内容给server,因为我们server的消息处理器中的接受Client的函数中做了如下处理:

 


  
  
  1. // 当客户端发送的消息到达时: 
  2.     @Override 
  3.     public void messageReceived(IoSession session, Object message) 
  4.             throws Exception { 
  5.         // // 我们己设定了服务器解析消息的规则是一行一行读取,这里就可转为String: 
  6.         // String s = (String) message; 
  7.         // // Write the received data back to remote peer 
  8.         // System.out.println("收到客户机发来的消息: " + s); 
  9.         // // 测试将消息回送给客户端 session.write(s+count); count++; 
  10.  
  11.         HimiObject ho = (HimiObject) message; 
  12.         System.out.println(ho.getName()); 
  13.  
  14.         ho.setName("serverHimi"); 
  15.         session.write(ho); 
  16.  
  17.     } 

Himi这里server处理client端发来的数据处理函数(如上代码)中,当Client发送数据过来的时候,将消息message强制转换成了一个HimiObject对象,然后改个name重写发给Client端,但是由于Client端是使用终端模拟登陆根本无法接受这个对象,所以会出异常;

但是到这里大家应该懂得,HimiObject类的作用了;哈哈

下面我们来书写Client客户端,对于建立一个Client端,其实步骤雷同,步骤如下:

        1 . 建立一个NioSocketConnector对象; 

        2. 设定过滤器

        3. 设定消息处理器

代码如下:

 


  
  
  1. /** 
  2.  * @author Himi 
  3.  */ 
  4. import java.net.InetSocketAddress; 
  5.  
  6. import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; 
  7. import org.apache.mina.core.future.ConnectFuture; 
  8. import org.apache.mina.filter.codec.ProtocolCodecFilter; 
  9. import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory; 
  10. import org.apache.mina.transport.socket.nio.NioSocketConnector; 
  11.  
  12. public class MainClient { 
  13.     public static void main(String[] args) { 
  14.         // 创建一个tcp/ip 连接 
  15.         NioSocketConnector connector = new NioSocketConnector(); 
  16.  
  17.         /*---------接收字符串---------*/ 
  18.         // //创建接收数据的过滤器 
  19.         // DefaultIoFilterChainBuilder chain = connector.getFilterChain(); 
  20.         // // 设定这个过滤器将一行一行(/r/n)的读取数据 
  21.         // chain.addLast("myChin", new ProtocolCodecFilter( 
  22.         // new TextLineCodecFactory())); 
  23.         /*---------接收对象---------*/ 
  24.         // 创建接收数据的过滤器 
  25.         DefaultIoFilterChainBuilder chain = connector.getFilterChain(); 
  26.         // 设定这个过滤器将以对象为单位读取数据 
  27.         ProtocolCodecFilter filter = new ProtocolCodecFilter( 
  28.                 new ObjectSerializationCodecFactory()); 
  29.         // 设定服务器端的消息处理器:一个SamplMinaServerHandler对象, 
  30.         chain.addLast("objectFilter",filter); 
  31.  
  32.         // 设定服务器端的消息处理器:一个 SamplMinaServerHandler 对象, 
  33.         connector.setHandler(new ClientMinaServerHanlder()); 
  34.         // Set connect timeout. 
  35.         connector.setConnectTimeoutCheckInterval(30); 
  36.         // 连结到服务器: 
  37.         ConnectFuture cf = connector.connect(new InetSocketAddress("localhost"
  38.                 9988)); 
  39.         // Wait for the connection attempt to be finished. 
  40.         cf.awaitUninterruptibly(); 
  41.         cf.getSession().getCloseFuture().awaitUninterruptibly(); 
  42.         connector.dispose(); 
  43.  
  44.     } 

不多说了,很eazy:那么我们继续看Clent端的消息处理器以及HimiObject:

ClentMinaServerHanlder:

 


  
  
  1. /** 
  2.  * @author Himi 
  3.  */ 
  4.  
  5. import org.apache.mina.core.service.IoHandlerAdapter; 
  6. import org.apache.mina.core.session.IoSession; 
  7.  
  8. public class ClientMinaServerHanlder extends IoHandlerAdapter { 
  9.     // 当一个客端端连结到服务器后 
  10.     @Override 
  11.     public void sessionOpened(IoSession session) throws Exception { 
  12. //      session.write("我来啦........"); 
  13.         HimiObject ho = new HimiObject(1,"Himi"); 
  14.         session.write(ho); 
  15.     } 
  16.  
  17.     // 当一个客户端关闭时 
  18.     @Override 
  19.     public void sessionClosed(IoSession session) { 
  20.         System.out.println("I'm Client &&  I closed!"); 
  21.     } 
  22.  
  23.     // 当服务器端发送的消息到达时: 
  24.     @Override 
  25.     public void messageReceived(IoSession session, Object message) 
  26.             throws Exception { 
  27. //      // 我们己设定了服务器解析消息的规则是一行一行读取,这里就可转为 String: 
  28. //      String s = (String) message; 
  29. //      // Write the received data back to remote peer 
  30. //      System.out.println("服务器发来的收到消息: " + s); 
  31. //      // 测试将消息回送给客户端 session.write(s); 
  32.  
  33.         HimiObject ho = (HimiObject) message; 
  34.         System.out.println(ho.getName()); 
  35.  
  36.     } 

Client的HimiObject与服务器Server的HimiObejct类一模一样!

可能有童鞋不理解为什么server端与client的HimiObject一模一样,这里Himi说下,通过Client端的消息处理器可以看出,当我们Client端连接到服务器后,首先会写给Server端一个HimiObject对象!那么服务器之前说过了,接受到Client端的消息后首先将消息强制转换成HimiObject对象然后处理;

既然Client端发的是Object,那么当然我们的服务器也要有对应的此Object对象才可以,否则如何获取这个Object?  大家应该很容易理解;

OK,不多说直接运行Client端,观察结果:

 

OK,结果正常。

    Client与Server消息逻辑如下:

    1. Client->传递HimiObject给Server

     2. Server端接受message强制转换HimiObject,并且设置其name为serverHimi,然后再传递给Client

    3. 客户端接受message强制转换HimiObject,然后获取此类的name打印出来!





本文转自 xiaominghimi 51CTO博客,原文链接:http://blog.51cto.com/xiaominghimi/969789,如需转载请自行联系原作者
目录
相关文章
|
SQL 分布式计算 Java
Apache IoTDB开发系统整合之Spark IoTDB Connecter
以下 TsFile 结构为例: TsFile 架构中有三个度量:状态、温度和硬件。
283 0
|
存储 缓存 监控
Apache IoTDB开发之运维和监控工具
目前,IoTDB为用户提供了使用Java的JConsole工具来监控系统状态或使用IoTDB的开放API来检查数据状态。启动JConsole工具并连接到IoTDB服务器后,咱们大家就可以基本了解IoTDB系统状态,包括CPU占用,内存信息等。
716 0
|
数据可视化 Java 物联网
Apache IoTDB开发之JMX 工具
Java VisualVM 是一个工具,它提供了一个可视化界面,用于在 Java 虚拟机 (JVM) 上运行时查看有关 Java 应用程序的详细信息,以及对这些应用程序进行故障排除和分析。
157 0
|
6月前
|
Apache 数据库
杨校老师课堂之基于Apache的数据库连接池DBCP的工具类开发
杨校老师课堂之基于Apache的数据库连接池DBCP的工具类开发
30 0
|
4月前
|
存储 分布式计算 物联网
Apache IoTDB进行IoT相关开发实践
当今社会,物联网技术的发展带来了许多繁琐的挑战,尤其是在数据库管理系统领域,比如实时整合海量数据、处理流中的事件以及处理数据的安全性。例如,应用于智能城市的基于物联网的交通传感器可以实时生成大量的交通数据。据估计,未来5年,物联网设备的数量将达数万亿。物联网产生大量的数据,包括流数据、时间序列数据、RFID数据、传感数据等。要有效地管理这些数据,就需要使用数据库。数据库在充分处理物联网数据方面扮演着非常重要的角色。因此,适当的数据库与适当的平台同等重要。由于物联网在世界上不同的环境中运行,选择合适的数据库变得非常重要。 原创文字,IoTDB 社区可进行使用与传播 一、什么是IoTDB 我
192 9
Apache IoTDB进行IoT相关开发实践
|
4月前
|
Java 持续交付 项目管理
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。它采用项目对象模型(POM)来描述项目,简化构建流程。Maven提供依赖管理、标准构建生命周期、插件扩展等功能,支持多模块项目及版本控制。在Java Web开发中,Maven能够自动生成项目结构、管理依赖、自动化构建流程并运行多种插件任务,如代码质量检查和单元测试。遵循Maven的最佳实践,结合持续集成工具,可以显著提升开发效率和项目质量。
62 1
|
4月前
|
Apache 开发者 Java
Apache Wicket揭秘:如何巧妙利用模型与表单机制,实现Web应用高效开发?
【8月更文挑战第31天】本文深入探讨了Apache Wicket的模型与表单处理机制。Wicket作为一个组件化的Java Web框架,提供了多种模型实现,如CompoundPropertyModel等,充当组件与数据间的桥梁。文章通过示例介绍了模型创建及使用方法,并详细讲解了表单组件、提交处理及验证机制,帮助开发者更好地理解如何利用Wicket构建高效、易维护的Web应用程序。
62 0
|
5月前
|
存储 分布式计算 物联网
Apache IoTDB进行IoT相关开发实践
IoTDB是专为物联网(IoT)设计的开源时间序列数据库,提供数据收集、存储、管理和分析。它支持高效的数据写入、查询,适用于处理大规模物联网数据,包括流数据、时间序列等。IoTDB采用轻量级架构,可与Hadoop和Spark集成,支持多种存储策略,确保数据安全和高可用性。此外,它还具有InfluxDB协议适配器,允许无缝迁移和兼容InfluxDB的API和查询语法,简化物联网项目的数据管理。随着物联网设备数量的快速增长,选择适合的数据库如IoTDB对于数据管理和分析至关重要。
263 12
|
5月前
|
存储 分布式计算 物联网
Apache IoTDB进行IoT相关开发实践
The article introduces IoTDB, an open-source time-series database designed for efficient management of IoT-generated data. It addresses challenges like real-time integration of massive datasets and security. IoTDB supports high-performance storage,
152 0
Apache IoTDB进行IoT相关开发实践
|
6月前
|
存储 分布式计算 物联网
Apache IoTDB进行IoT相关开发实践
IoTDB是面向物联网的时序数据库,专注于时间序列数据管理,提供高效的数据处理、集成Hadoop和Spark生态、支持多目录存储策略。它还具有InfluxDB协议适配器,允许无缝迁移原本使用InfluxDB的业务。文章讨论了IoTDB的体系结构,包括数据文件、系统文件和预写日志文件的存储策略,并介绍了如何配置数据存储目录。此外,还提及了InfluxDB版本和查询语法的支持情况。IoTDB在物联网数据管理和分析中扮演关键角色,尤其适合处理大规模实时数据。
114 5

推荐镜像

更多