MINA服务端的应用应用体系结构
基本上,服务器监听端口传入请求,处理它们并发送回复。它还为每个客户端创建和处理会话(无论我们是基于TCP或者UDP的时候)。
Server_arch.png
- IOAcceptor在网络上监听传入的连接/数据包
- 对于新链接,将会创建一个新的会话,并在该会话中处理来自IP地址/端口组合的所有后续请求
- 为会话接收的所有数据包将按照图中所示的方式遍历过滤器。过滤器可用于修改数据包的内容(如转换为对象,添加/删除信息等)。PacketEncoder/Decoder对于将原始字节转换为高级对象,非常有用。
- 最后数据包或者转换成对象的数据将加载到IOHandler中,IOHandler可以非常完美的处理业务需求。
示例TCP服务器
接下来将引导您完成构建基于MINA的程序的过程,逐步构建一个时间服务器。开发服务器端需要以下几个先决条件:
1.MINA 2.x Core
2.JDK1.5或者更高
3.SLF4J1.3.0或者更高(注1中的下载文件中已经包含了对应的包)
- Log4J 1.2 的用户需要的包:slf4j-api.jar,slf4j-log4j12.jar,和Log4J 1.2.x
- Log4J 1.3的用户需要的包:slf4j-api.jar,slf4j-log4j13.jar,和Log4J 1.3.x
- java.util.logging的用户需要的包:slf4j-api.jar和slf4j-jdk14.jar,
- 注:请确保你使用了正确的slf4j-*.jar匹配你的日志框架。
实际上, slf4j-log4j12.jar 和log4j-1.3.x.jar 不能一起使用,并且会发生故障。
开始服务器端代码
首先创建java project项目,和普通的创建方式一致,创建libs文件夹将需要的包复制进去:
项目结构.png
接下来创建对应的服务类:
package com.fmblzf.minaservice;
/**
*
* @Copy:2017-fmblzf
* @ProjectName:MINA_SERVER
* @ClassDecription:
* @ClassName:com.fmblzf.minaservice.MinaServerMain
* @Creator:zhaofeng
* @CreatTime:2017年5月27日 上午11:50:55
* @FixPerson:fmblzf
* @FixTime:2017年5月27日 上午11:50:55
* @Tag:
* @version V1.0
*
*/
public class MinaServerMain {
//设置端口号
private static final int PORT = 9321;
public static void main(String[] args) {
}
}
首先,我们需要一个将用于侦听传入连接的对象。由于该程序将基于TCP/IP,我们将在我们的程序中添加一个SocketAcceptor,我们创建对应的NioSocketAcceptor对象,并且将其绑定到PORT端口上。
IoAcceptor ioAcceptor = new NioSocketAcceptor();
ioAcceptor.bind(new InetSocketAddress(PORT));
接下来设置过滤器,配置Session,以及设置处理对象
public static void main(String[] args) throws IOException {
//首先,添加对应的网络监听对象,等待处理连接和回复消息
IoAcceptor ioAcceptor = new NioSocketAcceptor();
//添加过滤器
ioAcceptor.getFilterChain().addLast("logger",new LoggingFilter());//设置日志管理过滤器
ioAcceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));//设置字节处理过滤器
//添加IOHandler
ioAcceptor.setHandler(new MainServerHandler());
//添加Session配置
ioAcceptor.getSessionConfig().setReadBufferSize(2048);//设置读缓存区的大小
ioAcceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);//设置读写的空闲时间都是10秒
ioAcceptor.bind(new InetSocketAddress(PORT));
}
创建自定义的IoHandler对象
/**
* 逻辑处理类
* @Copy:2017-fmblzf
* @ProjectName:MINA_SERVER
*
* @ClassDecription:
* @ClassName:com.fmblzf.minaservice.MainServerHandler
* @Creator:fmblzf
* @CreatTime:2017年5月27日 下午12:41:08
* @FixPerson:fmblzf
* @FixTime:2017年5月27日 下午12:41:08
* @Tag:
* @version V1.0
*
*/
private static class MainServerHandler extends IoHandlerAdapter{
/**
* 接收到消息
* @see org.apache.mina.core.service.IoHandlerAdapter#messageReceived(org.apache.mina.core.session.IoSession, java.lang.Object)
*
*/
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
String str = message.toString();
if( str.trim().equalsIgnoreCase("quit") ) {
session.closeNow();
return;
}
Date date = new Date();
session.write( date.toString() );
System.out.println("Message written...");
}
@Override
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
System.out.println( "IDLE " + session.getIdleCount( status ));
}
/**
* 发送消息给客户端
* @see org.apache.mina.core.service.IoHandlerAdapter#messageSent(org.apache.mina.core.session.IoSession, java.lang.Object)
*
*/
@Override
public void messageSent(IoSession session, Object message)
throws Exception {
}
@Override
public void sessionCreated(IoSession session) throws Exception {
}
@Override
public void sessionOpened(IoSession session) throws Exception {
}
@Override
public void sessionClosed(IoSession session) throws Exception {
}
}
示例UDP服务器
因为MINA的统一API接口,所以UDP和TCP在结构上是一致的,只有IoAcceptor对应的实现类是不一致,所以接下来我们看一看UDP创建的核心代码:
/**
* 创建UDP连接
* @Title: createUdp
* @Description: TODO
* @throws IOException
*
*/
private static void createUdp() throws IOException {
IoAcceptor ioAcceptor = new NioDatagramAcceptor();
// 添加过滤器
ioAcceptor.getFilterChain().addLast("logger", new LoggingFilter());// 设置日志管理过滤器
ioAcceptor.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));// 设置字节处理过滤器
// 添加IOHandler
ioAcceptor.setHandler(new MainServerHandler());
// 添加Session配置
ioAcceptor.getSessionConfig().setReadBufferSize(2048);// 设置读缓存区的大小
ioAcceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);// 设置读写的空闲时间都是10秒
ioAcceptor.bind(new InetSocketAddress(PORT+1));
}
从代码我们可以看见,UDP的IoAcceptor的实现类是NioDatagramAcceptor,其他的结构编写都是一致。
至此我们的TCP/UDP的核心代码已经完成,至于其他的衍生部分,感兴趣的朋友可以参考官网来接着学习。
网友评论