1、先简单介绍下MINA:
Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP
协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),
Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异
步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型。
2.MINA框架的常用类
类NioSocketAcceptor用于创建服务端监听;
类NioSocketConnector用于创建客户端连接;
类IoSession用来保存会话属性和发送消息;
类IoHandlerAdapter用于定义业务逻辑,常用的方法有:
方法 定义
sessionCreated() 当会话创建时被触发
sessionOpened() 当会话开始时被触发
sessionClosed() 当会话关闭时被触发
sessionIdle() 当会话空闲时被触发
exceptionCaught() 当接口中其他方法抛出异常未被捕获时触发此方法
messageRecieved() 当接收到消息后被触发
messageSent() 当发送消息后被触发
3、应用示例
所需jar包slf4j-api.jar、slf4j-jdk14.jar、MINA-core-2.0.0-M1.jar。相关包可到官方网站下载。
首先定义一个业务逻辑处理器TimeServerHandler,继承自IoHandlerAdapter,实现的功能有:当客户端创建会话时会显示客户端设备的IP和端口;当客户端输入quit时结束会话;客户端输入其它内容时则向客户端发送当前时间。代码如下:
public class TimeServerHandler extends IoHandlerAdapter { @Override public void sessionCreated(IoSession session) { // 显示客户端的ip和端口 System.out.println(session.getRemoteAddress().toString()); } @Override public void messageReceived(IoSession session, Object message) throws Exception { String str = message.toString(); if (str.trim().equalsIgnoreCase("quit")) { session.close();// 结束会话 return; } Date date = new Date(); session.write(date.toString());// 返回当前时间的字符串 System.out.println("Message written..." + str); } }
定义一个类MinaTimeServer用来启动服务端:
public class MinaTimeServer { private static final int PORT = 9123; // 定义监听端口 private static IoAcceptor acceptor; public static void main(String[] args) throws IOException { acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast("logger", new LoggingFilter()); //acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));// 指定编码过滤器 acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory()));//支持中文 acceptor.setHandler(new TimeServerHandler());// 指定业务逻辑处理器 acceptor.setDefaultLocalAddress(new InetSocketAddress(PORT));// 设置端口号 acceptor.bind();// 启动监听 }
客户端:定义类TimeClientHandler来处理消息接收事件
public class TimeClientHandler extends IoHandlerAdapter { public TimeClientHandler() { } @Override public void messageReceived(IoSession session, Object message) throws Exception { System.out.println(message);//显示接收到的消息 } }
定义MinaTimeClient类用于连接服务端,并向服务端发送消息:
public class MinaTimeClient { public static void main(String[] args) { // 创建客户端连接器. NioSocketConnector connector = new NioSocketConnector(); connector.getFilterChain().addLast( "logger", new LoggingFilter() ); //connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); //设置编码过滤器 connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory())); connector.setConnectTimeout(30); connector.setHandler(new TimeClientHandler());//设置事件处理器 ConnectFuture cf = connector.connect(new InetSocketAddress("127.0.0.1", 9123));//建立连接 cf.awaitUninterruptibly();//等待连接创建完成 cf.getSession().write("hello");//发送消息 cf.getSession().write("quit");//发送消息 cf.getSession().getCloseFuture().awaitUninterruptibly();//等待连接断开 connector.dispose(); } }
运行服务端server,再启动客户端MinaTimeClient,可看到进行通讯信息交互。
另在MinaTimeServer类中增加下面方法进行客户端连接总数以及服务端主动向客户端发送信息等测试。
public static void startMinaServer(){ acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast("logger", new LoggingFilter()); //acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));// 指定编码过滤器 acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(new TextLineCodecFactory()));//支持中文 acceptor.setHandler(new TimeServerHandler());// 指定业务逻辑处理器 acceptor.setDefaultLocalAddress(new InetSocketAddress(PORT));// 设置端口号 try { acceptor.bind(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }// 启动监听 } /** * 获得客户端连接总数 * @return */ public static int getConNum(){ int num = acceptor.getManagedSessionCount(); System.out.println("num:" + num); return num; } /** * 向每个客户端发送消息 * @return */ public static void sendConMessage(){ IoSession session; Map conMap = acceptor.getManagedSessions(); Iterator iter = conMap.keySet().iterator(); while (iter.hasNext()) { Object key = iter.next(); session = (IoSession)conMap.get(key); session.write("" + key.toString()); } }