Apache Mina Server是一个网络通信应用框架,主要是对基于TCP/IP,UDP/IP协议栈的通信框架,Mina可以帮助快速开发高性能、高扩展性的网络通信应用,Mina提供了事件驱动、异步操作的编程模型。
Mina同时提供了网络通信的Server端、Client端的封装,无论是哪端,Mina在整个结构中都处于如下位置:
可见Mima的API将真正的网络通信与文明的应用程序隔离开来,你只需要关心你要发送、接收的数据及你的业务逻辑即可。
同样,无论是哪端,Mina的执行流程如下:
1)IoService:这个接口在一个线程上负责套接字的建立,拥有自己的Selector,监听是否有新连接被建立。
2) IoProcessor:这个接口在另一个线程上负责检查是否有数据在通道上读写,也就是说它也拥有自己的Selector。
3) IoFilter:这个接口定义一组拦截器,这些拦截器可以包括日志输出、黑名单过滤、数据编码、解码等,其中编码、解码最为重要,也是你要使用Mina时最关注的地方。
4) IoHandler:这个接口负责编写业务逻辑,也就是接收、发送数据的地方。
实例:简单的TCPServer
/**
* TCP SERVER
* @function :
* @author :jy
* @company :万里网
* @date :2011-7-23
*/
public class MyServer {
public static IoAcceptor acceptor = null;
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
acceptor = new NioSocketAcceptor();
acceptor.getSessionConfig().setReadBufferSize(2048);//读缓冲区大小
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);//进入空闲时间
acceptor.getSessionConfig().setUseReadOperation(true);//数据可读
acceptor.getSessionConfig().setWriteTimeout(30);//写超时时间
//字符过滤器
acceptor.getFilterChain().addLast("codec1", new ProtocolCodecFilter(new TextLineCodecFactory()));
//acceptor.getFilterChain().addLast("myIoFilter", new ReferenceCountingFilter(new MyIoFilter()));
//acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CmssSipcCodecFactory(Charset.forName("UTF-8"))));
//acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new FlightCodecFactory(Charset.forName("UTF-8"))));
//绑定业务逻辑
acceptor.setHandler(new MyIoHandler());
acceptor.bind(new InetSocketAddress(9123));//监听端口号
}
}
简单的Client:
/**
* @function :
* @author :jy
* @company :万里网
* @date :2011-7-24
*/
public class MyClient {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
IoConnector conneector = new NioSocketConnector();
conneector.setConnectTimeoutMillis(30000);
//conneector.getFilterChain().addLast("codec1", new ProtocolCodecFilter(new TextLineCodecFactory()));
//conneector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new CmssSipcCodecFactory(Charset.forName("UTF-8"))));
conneector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new FlightCodecFactory(Charset.forName("UTF-8"))));
conneector.getSessionConfig().setUseReadOperation(true);
conneector.setHandler(new MyClientHandler());
conneector.connect(new InetSocketAddress("localhost", 9123));
}
}
注:TCP Server与TCP Client必须都绑定Hanndler,否则会抛出异常。
Server Handler:myIoHandler
/**
* @function :
* @author :jy
* @company :万里网
* @date :2011-7-23
*/
public class MyIoHandler extends IoHandlerAdapter {
private final static Logger log = LoggerFactory.getLogger(MyIoHandler.class);
/**
* 接收到消息时调用的方法,也就是用于接收信息的方法。
* message一般是一个IoBuffer类,如果你使用了协议编码解码器,那么可以强制转换为你需要的类型。
* 通常都会使用协议编解码器的。
* 例如:使用TextLineCodecFactory协议编解码器,可以强制转换message为String类型。
*/
@Override
public void messageReceived(IoSession session, Object message){
Flight sms = (Flight)message;
//String sms = (String) message;
log.info("The message recevied is [" + sms + "]");
//session.write(new java.util.Date());
//session.close(true);
//session.write(session.getAttribute("test"));
// if(str.equals("all")){
// //sendAll();
// }
//
// if(str.endsWith("quit")){
// session.close(true);
// return;
// }
}
// /**
// * 这个方法当一个Session对象被创建的时候被调用。
// * 对于TCP连接来说,连接被接受的时候调用,但要注意此时TCP连接并未被建立,也就是连接的对象IoSession被创建完毕
// * 的时候,回调这个方法。
// * 对于UDP来说,当有数据包收到的时候回调这个方法,因为UDP是无连接的。
// */
// @Override
// public void sessionCreated(IoSession session){
// session.write("welcome!\r");
// }
//
/**
* 当程序自身出现异常时回调,一般这里关闭IoSession
*/
@Override
public void exceptionCaught(IoSession session, Throwable able) throws Exception {
able.printStackTrace();
}
//
// /**
// * 当发送消息成功时调用这个方法。
// * 注意,这里是发送成功之后,也就是说发送消息时不能用这个发方法的。
// */
// @Override
// public void messageSent(IoSession arg0, Object arg1) throws Exception {
// // TODO Auto-generated method stub
//
// }
//
// /**
// * 对于TCP来说,连接被关闭时,调用这个方法。
// * 对于UDP来说,IoSession的close()方法被调用时才会毁掉这个方法。
// */
// @Override
// public void sessionClosed(IoSession arg0) throws Exception {
// // TODO Auto-generated method stub
//
// }
//
// /**
// * 当IoSession的通道进入空闲状态时调用。
// * 对于UDP协议来说,这个方法始终不会被调用。
// */
// @Override
// public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception {
// // TODO Auto-generated method stub
//
// }
//
// /**
// * 当连接被打开时调用,它总是在sessionCreated()方法之后被调用。
// * 对于TCP,它是在连接被建立之后调用,可以在这里执行一些认证、发送数据操作等。
// * 对于UDP,这个方法与sessionCreated()没区别,但是紧跟其后执行。如果你每隔一段时间,发送一些数据,那么
// * sessionCreated()方法只会在第一次调用,但是sessionOpened()方法每次都会被调用。
// */
// @Override
// public void sessionOpened(IoSession arg0) throws Exception {
// // TODO Auto-generated method stub
//
// }
}
Client Hanlder:MyClientHandler
/**
* @function :
* @author :jy
* @company :万里网
* @date :2011-7-24
*/
public class MyClientHandler extends IoHandlerAdapter {
/* (non-Javadoc)
* @see org.apache.mina.core.service.IoHandler#sessionCreated(org.apache.mina.core.session.IoSession)
*/
@Override
public void sessionCreated(IoSession session) throws Exception {
// SmsObject sms = new SmsObject();
// sms.setSender("13721047855");
// sms.setReceiver("15855533814");
// sms.setMessage("hello MiNa");
// session.write(sms);
// Flight flight = new Flight();
// flight.setFirstCity("SHA");
// flight.setFirstDay("2011-07-28");
// flight.setFlightway("DOBUBLE");
// flight.setSecondCity("BJS");
// flight.setSecondDay("2011-07-29");
// flight.setThirdCity("SHA");
// session.write(flight);
//在建立了自定义数据Encode、Decode后,可以发送对象。
session.write("hello Mina");
}
}