多语言展示
当前在线:1052今日阅读:61今日分享:18

apache mina服务器

这是针对初期了解mina框架的一套简单的服务器构架
工具/原料
1

myeclipse或者eclipse

2

jdk1.7及以上

方法/步骤
1

了解Apache mina框架:Mina 同时提供了网络通信的Server 端、Client 端的封装,无论是哪端,Mina 在整个网通通信结构中都处于如下的位置:可见Mina 的API 将真正的网络通信与我们的应用程序隔离开来,你只需要关心你要发送、接收的数据以及你的业务逻辑即可。同样的,无论是哪端,Mina 的执行流程如下所示:(1.) IoService:这个接口在一个线程上负责套接字的建立,拥有自己的Selector,监听是否有连接被建立。(2.) IoProcessor:这个接口在另一个线程上,负责检查是否有数据在通道上读写,也就是说它也拥有自己的Selector,这是与我们使用JAVA NIO 编码时的一个不同之处,通常在JAVA NIO 编码中,我们都是使用一个Selector,也就是不区分IoService与IoProcessor 两个功能接口。另外,IoProcessor 负责调用注册在IoService 上的过滤器,并在过滤器链之后调用IoHandler。(3.) IoFilter:这个接口定义一组拦截器,这些拦截器可以包括日志输出、黑名单过滤、数据的编码(write 方向)与解码(read 方向)等功能,其中数据的encode 与decode是最为重要的、也是你在使用Mina 时最主要关注的地方。(4.) IoHandler:这个接口负责编写业务逻辑,也就是接收、发送数据的地方。

2

一:建设一个简单的mina服务器1.所需的jar包

3

2.服务器的架设第一步:编写IoService按照上面的执行流程,我们首先需要编写IoService,IoService 本身既是服务端,又是客户端,我们这里编写服务端,所以使用IoAcceptor 实现,由于IoAcceptor 是与协议无关的,因为我们要编写TCPServer,所以我们使用IoAcceptor 的实现NioSocketAcceptor,实际上底层就是调用java.nio.channels.ServerSocketChannel 类。当然,如果你使用了Apache 的APR 库,那么你可以选择使AprSocketAcceptor 作为TCPServer 的实现,据传说Apache APR库的性能比JVM 自带的本地库高出很多。那么IoProcessor 是由指定的IoService 内部创建并调用的,我们并不需要关心。

4

这段代码我们初始化了服务端的TCP/IP 的基于NIO 的套接字,然后调用IoSessionConfig设置读取数据的缓冲区大小、读写通道均在10 秒内无任何操作就进入空闲状态。(2.) 第二步:编写过滤器这里我们处理最简单的字符串传输,Mina 已经为我们提供了TextLineCodecFactory 编解码器工厂来对字符串进行编解码处理。(这是mina自带的编码器)

5

这段代码要在acceptor.bind()方法之前执行,因为绑定套接字之后就不能再做这些准备工作了。mina有自带的编码器,也就是说我们能重写编码器,自定义编码器:

6

也就是我们之前说的解码与编码(数据的编码(write 方向)与解码(read 方向),其中数据的encode 与decode是最为重要的)因为我们是基于TCP协议传输数据,所以用的是字节流的方式,下面是简单的字节流数据解码decode(解码)

7

encode(编码)

8

数据包的格式定义(自定义编码与解码之后,那么我们也会自定义包的格式传输,包的格式一般是protobuf,json,Serialization;注意:编码与解码前后端格式一定要一样)包分为:包头(协议头(101...))+包体(具体数据)

9

数据包长(包体长度)+命令头(包头)+包体=包的整体发送格式

10

这就是整个编码的过程,IoBuffer.allocate(0 + 4)这个方法内部通过SimpleBufferAllocator 创建一个实例,指定初始化容量下面是通过编码之后的格式怎么解码:

11

oldPosition是获取当前IoBuffer的初始化位置(0)然后我们根据编码时候的格式解码编码的第一步是放入一个short的包长,那么我们这边解码也会先获取包长也是上面的short length = buf.getShort();那么获取完包长之后那么我们就要获取第二个位置的命令头,编码时候放的也是short那么我们取得时候也是short,取完之后整个buf剩下的就是我们要获得的数据包最后在获取到数据包,转换为我们自定义的数据包对象,输出出去

12

(3.) 第三步:编写IoHandler

13

这段代码也要在acceptor.bind()方法之前执行。IoHandler 可以说是我们具体的业务处理器

14

当客户端与服务器连接之后,会创建连接,在打开连接,然后服务器会是一个等待状态,当客户端发送消息过来之后,会调用messageReceived方法,当服务器返回给客户端消息也会调用messageSent方法,当客户端和服务器的连接断开会调用sessionClose()方法;那么说到之前,当解码一切顺利的执行到out.write(packet);方法时,消息就会走到messageReceived方法里面,这个时候我们就可以做具体的逻辑处理了

15

方法中message就是从解码器过来的数据包,所以我们可以直接强转为我们自定义的包对象,而session就是客户端与服务器建立好连接之后,所产生的一个标识,也是每一个客户端和服务器的唯一标识之后我们就可以做具体的业务处理:比如消息分发到具体的某个业务逻辑里面去

16

这个方法是我写的一个简单的消息分发

17

我们会根据某种算法得出协议头,也就是packet里面的cmd字段,我这是简单然后根据协议头再次转发到具体的业务层

18

这是就是具体的业务层,我这边将接收到的数据打印出来,然后又封装返回的消息给客户端我使用的就是protobuf方式,最终还是会转换成字节数组然后发送给客户端

推荐信息