目录
Mina是什么?
JAVA里的几种网络编程Api
Mina架构简介
客户端建立连接的流程
Mina框架使用
Apache MINA 是一个网络应用框架,有助于用户非常方便地开发高性能、高伸缩性的网络应用。它通过Java NIO提供了一个抽象的、事件驱动的、异步的位于各种传输协议(如TCP/IP和UDP/IP)之上的API,Apache MINA 通常可被称之为NIO 框架库;客户端/服务器框架库;或者一个网络socket库。
BIO: 传统的同步阻塞模型开发中ServerSocket负责绑定IP地址,启动监听端口;Socket负责发起连接操作。连接成功后,双方通过输入和输出流进行同步阻塞式通信。 简单的描述一下BIO的服务端通信模型:采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责监听客户端的连接,它接收到客户端连接请求之后为每个客户端创建一个新的线程进行链路处理没处理完成后,通过输出流返回应答给客户端,线程销毁。即典型的一请求一应答通宵模型。
NIO: 程序需要调用Seletor.select()方法,阻塞获取就绪的channel。然后从channel中读取数据做响应的处理。这样一个线程就可以处理多个请求,程序只需要处理已经就就绪的channel就ok了。
AIO: 程序调用AIO的accept方法并传入Completionhandler,该方法是非阻塞方法。 等数据准备完成后回调Completionhandler处理响应操作。
1、通过SocketConnector 同服务端建立连接;
2、连接建立之后 I/O的读写交给了I/O Processor线程,I/O Processor是多线程的;
3、通过I/O Processor 读取的数据经过IoFilterChain里所有配置的IoFilter,IoFilter进行消息的过滤,格式的转换,在这个层面可以制定一些自定义的协议;
4、最后IoFilter将数据交给 Handler 进行业务处理,完成了整个读取的过程;写入过程也是类似,只是刚好倒过来,通过IoSession.write 写出数据,然后Handler进行写入的业务处理,处理完成后交给IoFilterChain,进行消息过滤和协议的转换,最后通过 I/O Processor 将数据写出到 socket 通道。
第一步是创建Connector对象并初始化配置信息
private void init() {
ConnectConfig config = new ConnectConfig.Builder(getApplicationContext())
.setIp(Constant.SOCKET_IP)
.setPort(9989)
.setReadBufferSize(10240)
.setConnectionTimeout(10000)
.bulid();
//创建连接对象
mConnection = new NioSocketConnector();
mConnection.getSessionConfig().setReadBufferSize(mConfig.getReadBufferSize());
//读写通道10秒内无操作进入空闲状态
mConnection.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
/* 设置链接超时时间 */
mConnection.setConnectTimeoutMillis(mConfig.getConnectionTimeout());
//设置过滤
mConnection.getFilterChain().addLast("logger",new LoggingFilter());
//使用对象编码解码器
// mConnection.getFilterChain().addLast("codec",new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
//设定这个过滤器将一行一行的读取数据
mConnection.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset
.forName("UTF-8"),
LineDelimiter.UNIX.getValue(),
LineDelimiter.UNIX.getValue())));
//字节数组编解码器
// mConnection.getFilterChain().addLast("codec",new ProtocolCodecFilter(new ByteArrayCodecFactory()));
// 指定业务逻辑处理器
mConnection.setHandler(new DefaultHandler(mContext.get()));
//设置心跳工程
KeepAliveMessageFactory heartBeatFactory = new KeepAliveMessageFactory() {
@Override
public boolean isRequest(IoSession ioSession, Object o) {
//是否心跳请求报文
return false;
}
@Override
public boolean isResponse(IoSession ioSession, Object o) {
//是否服务器心跳响应报文
return false;
}
@Override
public Object getRequest(IoSession ioSession) {
//生成心跳请求报文
if (TextUtils.isEmpty(HEARTBEATREQUEST)){
HeartBeatRequest infoRequest = new HeartBeatRequest();
HEARTBEATREQUEST= JsonUtil.serialize(request);}
Log.d(TAG,HEARTBEATREQUEST);
return HEARTBEATREQUEST;
}
@Override
public Object getResponse(IoSession ioSession, Object o) {
return null;
}
};
当读操作空闲时发送心跳
KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory);
// 设置心跳包请求后超时无反馈情况下的处理机制,默认为关闭连接,在此处设置为输出日志提醒
heartBeat.setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler.LOG);
/** 是否回发 */
heartBeat.setForwardEvent(false);
/** 发送频率 */
heartBeat.setRequestInterval(mConfig.getHeartBeatRate());
/** 设置心跳包请求后 等待反馈超时时间。 超过该时间后则调用KeepAliveRequestTimeoutHandler.CLOSE */
heartBeat.setRequestTimeout(mConfig.getHeartTimeOut());
//connector.getSessionConfig().setKeepAlive(true);
mConnection.getFilterChain().addLast("heartbeat", heartBeat);
//connector.getFilterChain().addLast("reconnect", new KeepAliveRequestTimeoutHandlerImpl()); //心跳超时后的处理,这里先默认处理
// 监听客户端是否断线
mConnection.addListener(new IoServiceListener() {
@Override
public void serviceActivated(IoService ioService) throws Exception {
}
@Override
public void serviceIdle(IoService ioService, IdleStatus idleStatus) throws Exception {
}
// 向客服端发送消息后会调用此方法
@Override
public void serviceDeactivated(IoService ioService) throws Exception {
}
@Override
public void sessionCreated(IoSession ioSession) throws Exception {
}
@Override
public void sessionClosed(IoSession ioSession) throws Exception {
}
@Override
public void sessionDestroyed(IoSession arg0) throws Exception {
Log.e(TAG,"断开连接");
// TODO Auto-generated method stub
while (isRun) {
Log.d(TAG,"重连。。。");
boolean isConnection = connect();
if (isConnection) {
//当请求成功的时候,跳出循环
Log.d(TAG,"重连成功");
break;
}
try {
Thread.sleep(5000);
} catch (Exception e) {
}
}
}
});
}
第二步是与服务器建立连接
/**
* 与服务器连接的方法
* @return
*/
public boolean connect(){
try{
mAddress = new InetSocketAddress(mConfig.getIp(),mConfig.getPort());
//域名解析失败
if(mAddress.isUnresolved()){
Log.e(TAG,"网络错误,域名解析失败");
return false;
}
//设置连接地址
mConnection.setDefaultRemoteAddress(mAddress);
ConnectFuture future =mConnection.connect();
future.awaitUninterruptibly();
mSessioin = future.getSession();
//session为空表示连接失败
if (mSessioin!=null&&mSessioin.isConnected()) {
return true;
}
Log.e(TAG,"连接失败");
return false;
}catch (Exception e){
Log.e(TAG,"连接出现异常");
return false;
}
}
第三步是定义逻辑层处理类(Handler)
private class DefaultHandler extends IoHandlerAdapter{
private Context context;
public DefaultHandler(Context context) {
this.context = context;
}
/**
* 连接成功时回调的方法
* @param session
* @throws Exception
*/
@Override
public void sessionOpened(IoSession session) throws Exception {
//当与服务器连接成功时,将我们的session保存到我们的sesscionmanager类中,从而可以发送消息到服务器
SessionManager.getmInstance().setIoSession(session);
Log.d(TAG,"连接成功");
}
/**
* 接收到消息时回调的方法
* @param session
* @param message
* @throws Exception
*/
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
Log.d(TAG,message.toString());
}
}
最后附上源码链接
https://download.csdn.net/download/brilliant_wgh/10882471