这是一篇学习笔记类型的文章,比较熟悉mina的同学就不用看了。我是初学,写这篇笔记主要是为了自己总结学习和以后使用。当然若是不嫌弃来看看我也是非常欢迎的。
一,Mina是什么
mina是apache公司的一款开源项目,基于长连接,可以实现客户端与服务器端的数据交互,做即时通讯比较适合。
1. 长连接的基本概念:与http短连接相反,通过某种方式与服务器一直保持连接就叫长连接。
2. 长连接原理:
- 底层都是基于TCP/IP协议
- 通过Socket,ServerSocket与服务器保持连接
- 服务端一般使用ServerSocket建立监听,监听客户端与之连接
- 客户端使用Socket,指定主机地址和端口号,与服务器进行连接
3. 长连接的意义:
- 通过长连接,可以实现服务器主动向客户端推送消息
- 通过长连接,可以减少客户端对服务器的轮询
- 通信效率远高于http
二,Mina的优势
- 非常适合C/S架构的通信框架
- apache出品的开源项目,可靠性较好
- 学习资料比较多
- 使用起来比较简单
三,核心类
- IoService接口
- AbstractIoService
- IoAcceptor
- IoConnector
- LoggingFilter 记录mina所有日志
- ProtocolCodecFilter数据转化过滤器
- CompressionFilter数据压缩过滤器
- SSLFilter 数据加密过滤器
- IoSession类
- Handler类
- sessionCreated/sessionOpen/sessionClosed
- messageReceived/messageSent
- exceptionCaught
四.服务器端的构建
用到的jar包:mina-core-2.0.7.jar slf4j-log4j12-1.7.6.jar slf4j-api-1.7.6.jar log4j-1.2.14.jar (日志管理包)。jar包不够的话可以在官网上面下载。
代码:
public static void main(String[] args) {
IoAcceptor acceptor = new NioSocketAcceptor();
// 添加我们的日志过滤器
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast("codec",
new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
acceptor.setHandler(new DemoServerHandler());
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
try {
acceptor.bind(new InetSocketAddress(9223));
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("启动服务");
}
/**
* 负责我们session对象的创建监听以及消息发送和接收的监听
*
* @author huan
*
*/
private static class DemoServerHandler extends IoHandlerAdapter {
@Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("........sessionCreated");
super.sessionCreated(session);
}
@Override
public void sessionOpened(IoSession session) throws Exception {
System.out.println("........sessionOpened");
super.sessionOpened(session);
}
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
super.messageReceived(session, message);
String str = message.toString();
session.write(new Date().toString());
System.out.println("接收到的数据:" + str);
}
@Override
public void messageSent(IoSession session, Object message)
throws Exception {
super.messageSent(session, message);
}
@Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println("........sessionClosed");
super.sessionClosed(session);
}
}
四,Mina客户端创建步骤。
需要的jar包:mina-core-2.0.7.jar slf4j-android-1.6.1-RC1.jar
1. 创建一个Service,用来和远程服务器连接
代码:
Service中
@Override
public void onCreate() {
super.onCreate();
//创建线程
thread = new ConnectionThread("mina", getApplicationContext());
//启动线程
thread.start();
}
ConnectionThread继承HandlerThread,在其中的onLooperPrepared方法中,调用ConnectionManager对象与服务器进行连接。
2. 封装一个ConnectionManager类来提供与服务器连接的方法
ConnectionManager中控制与服务器的连接
private void init() {
mAddress = new InetSocketAddress(mConfig.getIp(), mConfig.getPort());
mConnection = new NioSocketConnector();
mConnection.getSessionConfig().setReadBufferSize(mConfig.getReadBufferSize());
mConnection.getFilterChain().addLast("logging", new LoggingFilter());
mConnection.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
mConnection.setHandler(new DefaultHandler(mContext.get()));
mConnection.setDefaultRemoteAddress(mAddress);
}
/**
* 外层调用,取得与服务器的连接
*
* @return
*/
public boolean connect() {
try {
ConnectFuture future = mConnection.connect();
future.awaitUninterruptibly();//一直等到它连接为止
mSession = future.getSession();
SessionManager.getInstance().setIoSession(mSession);
} catch (Exception e) {
return false;
}
return mSession == null ? false : true;
}
3. 在Service中启动线程,调用ConnectionManager完成连接的创建。
4. SessionManager类,在其中控制终与服务器进行通讯的对象IoSession,使用了单例模式。
private static SessionManager sessionManager;
//最终与服务器进行通讯的对象
private IoSession ioSession;
private SessionManager() {
}
public static SessionManager getInstance() {
if (sessionManager == null) {
synchronized (SessionManager.class) {
if (sessionManager == null) {
sessionManager = new SessionManager();
}
}
}
return sessionManager;
}
/**
* 将对象写到服务器
*
* @param msg
*/
public void writeToServer(Object msg) {
if (ioSession != null) {
ioSession.write(msg);
}
}
public void colseSession() {
if (ioSession != null) {
ioSession.closeOnFlush();
}
}