【APACHE MINA2.0开发之一】搭建APACHE MINA框架并实现SERVER与CLIENT端的简单消息传递!

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 
转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/apache-mina/831.html

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

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

/**

* @author Himi

*/

 

import java.io.Serializable;

 

public class HimiObject implements Serializable{

 

public HimiObject(int id,String name){

this.id=id;

this.name=name;

}

 

private int id;

 

private String name;

 

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

 

}

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

 

ClientMinaServerHanlder.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

/**

* @author Himi

*/

 

import org.apache.mina.core.service.IoHandlerAdapter;

import org.apache.mina.core.session.IdleStatus;

import org.apache.mina.core.session.IoSession;

 

public class ClientMinaServerHanlder extends IoHandlerAdapter {

 

private int count = 0;

 

// 当一个新客户端连接后触发此方法.

public void sessionCreated(IoSession session) {

System.out.println("新客户端连接");

}

 

// 当一个客端端连结进入时 @Override

public void sessionOpened(IoSession session) throws Exception {

count++;

System.out.println("第 " + count + " 个 client 登陆!address: : "

+ session.getRemoteAddress());

 

}

 

// 当客户端发送的消息到达时:

@Override

public void messageReceived(IoSession session, Object message)

throws Exception {

// // 我们己设定了服务器解析消息的规则是一行一行读取,这里就可转为String:

// String s = (String) message;

// // Write the received data back to remote peer

// System.out.println("收到客户机发来的消息: " + s);

// // 测试将消息回送给客户端 session.write(s+count); count++;

 

HimiObject ho = (HimiObject) message;

System.out.println(ho.getName());

 

ho.setName("serverHimi");

session.write(ho);

 

}

 

// 当信息已经传送给客户端后触发此方法.

@Override

public void messageSent(IoSession session, Object message) {

System.out.println("信息已经传送给客户端");

 

}

 

// 当一个客户端关闭时

@Override

public void sessionClosed(IoSession session) {

System.out.println("one Clinet Disconnect !");

}

 

// 当连接空闲时触发此方法.

@Override

public void sessionIdle(IoSession session, IdleStatus status) {

System.out.println("连接空闲");

}

 

// 当接口中其他方法抛出异常未被捕获时触发此方法

@Override

public void exceptionCaught(IoSession session, Throwable cause) {

System.out.println("其他方法抛出异常");

}

 

}

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

/**

* @author Himi

*/

 

import java.io.IOException;

import java.net.InetSocketAddress;

 

import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;

import org.apache.mina.filter.codec.ProtocolCodecFilter;

import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;

import org.apache.mina.transport.socket.SocketAcceptor;

import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

 

public class MinaServer {

 

/**

* @param args

*/

 

public static void main(String[] args) {

//创建一个非阻塞的server端Socket ,用NIO

SocketAcceptor acceptor = new NioSocketAcceptor();

 

/*---------接收字符串---------*/

// //创建一个接收数据过滤器

// DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();

// //设定过滤器一行行(/r/n)的读取数据

// chain.addLast("mychin", new ProtocolCodecFilter(new TextLineCodecFactory()   ));

/*---------接收对象---------*/

//创建接收数据的过滤器

DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();

//设定这个过滤器将以对象为单位读取数据

ProtocolCodecFilter filter= new ProtocolCodecFilter(new ObjectSerializationCodecFactory());

chain.addLast("objectFilter",filter);

 

//设定服务器消息处理器

acceptor.setHandler(new ClientMinaServerHanlder());

//服务器绑定的端口

int bindPort = 9988;

//绑定端口,启动服务器

try {

acceptor.bind(new InetSocketAddress(bindPort));

} catch (IOException e) {

System.out.println("Mina Server start for error!"+bindPort);

e.printStackTrace();

}

System.out.println("Mina Server run done! on port:"+bindPort);

}

}

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

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

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

        2.设置过滤器

        3. 设置消息处理器

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

OK,这里多说一些:

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

1

2

3

4

//创建一个接收数据过滤器

DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();

//设定过滤器一行行(/r/n)的读取数据

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

3

4

5

//创建接收数据的过滤器

DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();

//设定这个过滤器将以对象为单位读取数据

ProtocolCodecFilter filter= new ProtocolCodecFilter(new ObjectSerializationCodecFactory());

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

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// 当客户端发送的消息到达时:

@Override

public void messageReceived(IoSession session, Object message)

throws Exception {

// // 我们己设定了服务器解析消息的规则是一行一行读取,这里就可转为String:

// String s = (String) message;

// // Write the received data back to remote peer

// System.out.println("收到客户机发来的消息: " + s);

// // 测试将消息回送给客户端 session.write(s+count); count++;

 

HimiObject ho = (HimiObject) message;

System.out.println(ho.getName());

 

ho.setName("serverHimi");

session.write(ho);

 

}

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

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

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

        1 . 建立一个NioSocketConnector对象; 

        2. 设定过滤器

        3. 设定消息处理器

代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

/**

* @author Himi

*/

import java.net.InetSocketAddress;

 

import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;

import org.apache.mina.core.future.ConnectFuture;

import org.apache.mina.filter.codec.ProtocolCodecFilter;

import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;

import org.apache.mina.transport.socket.nio.NioSocketConnector;

 

public class MainClient {

public static void main(String[] args) {

// 创建一个tcp/ip 连接

NioSocketConnector connector = new NioSocketConnector();

 

/*---------接收字符串---------*/

// //创建接收数据的过滤器

// DefaultIoFilterChainBuilder chain = connector.getFilterChain();

// // 设定这个过滤器将一行一行(/r/n)的读取数据

// chain.addLast("myChin", new ProtocolCodecFilter(

// new TextLineCodecFactory()));

/*---------接收对象---------*/

// 创建接收数据的过滤器

DefaultIoFilterChainBuilder chain = connector.getFilterChain();

// 设定这个过滤器将以对象为单位读取数据

ProtocolCodecFilter filter = new ProtocolCodecFilter(

new ObjectSerializationCodecFactory());

// 设定服务器端的消息处理器:一个SamplMinaServerHandler对象,

chain.addLast("objectFilter",filter);

 

// 设定服务器端的消息处理器:一个 SamplMinaServerHandler 对象,

connector.setHandler(new ClientMinaServerHanlder());

// Set connect timeout.

connector.setConnectTimeoutCheckInterval(30);

// 连结到服务器:

ConnectFuture cf = connector.connect(new InetSocketAddress("localhost",

9988));

// Wait for the connection attempt to be finished.

cf.awaitUninterruptibly();

cf.getSession().getCloseFuture().awaitUninterruptibly();

connector.dispose();

 

}

}

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

ClentMinaServerHanlder:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

/**

* @author Himi

*/

 

import org.apache.mina.core.service.IoHandlerAdapter;

import org.apache.mina.core.session.IoSession;

 

public class ClientMinaServerHanlder extends IoHandlerAdapter {

// 当一个客端端连结到服务器后

@Override

public void sessionOpened(IoSession session) throws Exception {

// session.write("我来啦........");

HimiObject ho = new HimiObject(1,"Himi");

session.write(ho);

}

 

// 当一个客户端关闭时

@Override

public void sessionClosed(IoSession session) {

System.out.println("I'm Client &&  I closed!");

}

 

// 当服务器端发送的消息到达时:

@Override

public void messageReceived(IoSession session, Object message)

throws Exception {

// // 我们己设定了服务器解析消息的规则是一行一行读取,这里就可转为 String:

// String s = (String) message;

// // Write the received data back to remote peer

// System.out.println("服务器发来的收到消息: " + s);

// // 测试将消息回送给客户端 session.write(s);

 

HimiObject ho = (HimiObject) message;

System.out.println(ho.getName());

 

}

}

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打印出来!

时间: 2024-10-31 16:07:37

【APACHE MINA2.0开发之一】搭建APACHE MINA框架并实现SERVER与CLIENT端的简单消息传递!的相关文章

【APACHE MINA2.0开发之二】自定义实现SERVER/CLIENT端的编解码工厂(自定义编码与解码器)!

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/apache-mina/839.html 在上一篇博文中已经简单介绍过"过滤器"的概念,那么在Mina 中的协议编解码器通过过滤器 ProtocolCodecFilter 构造,这个过滤器的构造方法需 要一个 ProtocolCodecFactory,这从前面注册 TextLineCodecFactory 的代码就可以看出来. Pr

关于cs程序中使用mina2框架,server与client端的session不是同一个,不能实现数据互通

问题描述 我在开发cs程序中使用mina2框架,server与client端的session不是同一个,不能实现数据互通.是不是本来就不是同一个,还是哪里需要设置? 解决方案

Apache Hama 0.6.3 发布,并行计算框架

http://www.aliyun.com/zixun/aggregation/14417.html">Apache Hama 0.6.3 发布,该版本兼容 Hadoop 2,增加了基于 BSP 的机器学习算法.动态图形 API 等. Hama 是个计算框架,基于BSP (Bulk Synchronous Parallel大容量同步并行)计算技术,主要针 对大规模科学的计算.

在Apache Geronimo上开发和部署Apache Pluto门户应用程序

简介: 即使 Apache Geronimo 的功能集中缺少预先集成的门户服务器支持, 您仍可以使用 Geronimo 作为门户应用程序的测试和部署环境.本文将引导您逐步完成在 Geronimo 部署 Apache Pluto 驱动器和 容器的过程,为您的门户应用程序提供百分之百的开放源码环境.然后了解如何 在 Pluto 和 Geronimo 中开发.部署和测试样例门户应用程序. Apache Pluto 和 Apache Geronimo:快速入门 Apache Pluto 是 Java P

apache php mysql开发环境安装教程_php实例

apache php mysql开发环境搭建教程,分享给大家,供大家参考 0.资源链接: 360云盘:https://yunpan.cn/c6wpzYwbfmLJY (提取码:0190) 1.首先安装编译器环境 即如下文件: 2.安装apache+php+mysql 即如下文件: 2.1.安装apache 2.1.1安装 只说关键几点 2.1.1.1 2.1.1.2 2.1.1.3 2.1.1.4.在浏览器地址栏输入:localhost ,若出现以下页面,说明您已成功安装apache 2.1.2

apache php mysql开发环境安装教程

apache php mysql开发环境搭建教程,分享给大家,供大家参考 0.资源链接: 360云盘:https://yunpan.cn/c6wpzYwbfmLJY (提取码:0190) 1.首先安装编译器环境 即如下文件: 2.安装apache+php+mysql 即如下文件: 2.1.安装apache 2.1.1安装 只说关键几点 2.1.1.1 2.1.1.2 2.1.1.3 2.1.1.4.在浏览器地址栏输入:localhost ,若出现以下页面,说明您已成功安装apache 2.1.2

Apache 配置详解(最好的APACHE配置教程)_php技巧

Apache的配置 Apache的配置由httpd.conf文件配置,因此下面的配置指令都是在httpd.conf文件中修改. 主站点的配置(基本配置) (1) 基本配置: ServerRoot "/mnt/software/apache2" #你的apache软件安装的位置.其它指定的目录如果没有指定绝对路径,则目录是相对于该目录. PidFile logs/httpd.pid #第一个httpd进程(所有其他进程的父进程)的进程号文件位置. Listen 80 #服务器监听的端口号

Apache MINA v2.0.3发布 一个网络应用程序框架

Apache MINA是一个网络应用程序框架,用来帮助用户简单地开发高性能和高可靠性的网络应用程序.它提供了一个通过Java NIO在不同的传输例如TCP/IP和UDP/IP上抽象的事件驱动的异步API. Apache MINA 也称为: ● NIO 框架库 ● 客户端服务器框架库 ● 一个网络套接字库 MINA虽然简单但是仍然提供了全功能的网络应用程序框架: ● 为不同的传输类型提供了统一的API: ○ 通过Java NIO提供TCP/IP 和 UDP/IP支持 ○ 通过RXTX提供串口通讯(

linux下apache+mysql+php开发环境纯源代码编译搭建

apache|mysql|编译|源代码 记录一下我在fedora core 1下通过源代码编译出来的apache+mysql+php开发环境的全部过程 通常安装一台服务器当然使用rpm是最方便的,不需要考虑太多配置的问题,就可以轻松获得需要的环境了.不过rpm包互相关联的问题也不是这么容易解决. apache,mysql,php这三个应用从源代码编译安装还是比较简单的,配置参数不算复杂,而且没有太多的依赖关系,从源码编译出来的系统也比较稳定一些,方便未来打补丁和升级工作. 编译安装的前提是,系统