本文是在Android客户端上与服务器建立长连接,固定时间端发送心跳包。但发送初始化消息后,一直不能回调IoHandlerAdapter的messageReceived函数,虽然已经打印了接收Log(RECEIVED: HeapBuffer[...])。
本文基于:mina-core-2.0.16.jar和slf4j-android-1.6.1-RC1.jar,主要代码如下:
......
connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(PushConstant.CONNECT_TIMEOUT);
// 设置日志输出工厂
connector.getFilterChain().addLast("logger", new LoggingFilter());
// 设置请求和响应对象的编解码操作
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ByteArrayCodecFactory()));
// 创建心跳工厂
ClientKeepAliveMessageFactory heartBeatFactory = new ClientKeepAliveMessageFactory();
// 当读操作空闲时发送心跳
KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory, IdleStatus.READER_IDLE);
// 设置是否将事件继续往下传递
heartBeat.setForwardEvent(true);
// 设置心跳包请求后超时无反馈情况下的处理机制,默认为关闭连接,在此处设置为输出日志提醒
heartBeat.setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler.LOG);
//设置心跳频率
heartBeat.setRequestInterval(180);
connector.getFilterChain().addLast("keepAlive", heartBeat);
// 设置接收和发送缓冲区大小
connector.getSessionConfig().setReceiveBufferSize(1024);
connector.getSessionConfig().setSendBufferSize(1024);
// 设置读取空闲时间:单位为s
connector.getSessionConfig().setReaderIdleTime(180);
// 设置长连接业务逻辑处理类Handler
LongConnectHandler longConnectHandler = new LongConnectHandler();
connector.setHandler(longConnectHandler);
......
......
private class LongConnectHandler extends IoHandlerAdapter {
@Override
public void sessionCreated(IoSession session) throws Exception {
super.sessionCreated(session);
}
@Override
public void sessionClosed(IoSession session) throws Exception {
super.sessionClosed(session);
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
super.exceptionCaught(session, cause);
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
System.err.println("接受消息成功...");
super.messageReceived(session, message);
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
super.messageSent(session, message);
}
}
ClientKeepAliveMessageFactory类实现如下:
private class ClientKeepAliveMessageFactory implements 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) {
try {
return IoBuffer.wrap(heartBeat().bytes());
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
@Override
public Object getResponse(IoSession ioSession, Object o) {
return null;
}
}
@Override
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
try {
if (messageFactory.isRequest(session, message)) {
Object pongMessage = messageFactory.getResponse(session, message);
if (pongMessage != null) {
nextFilter.filterWrite(session, new DefaultWriteRequest(pongMessage));
}
}
if (messageFactory.isResponse(session, message)) {
resetStatus(session);
}
} finally {
if (!isKeepAliveMessage(session, message)) {
nextFilter.messageReceived(session, message);
}
}
}
private boolean isKeepAliveMessage(IoSession session, Object message) {
return messageFactory.isRequest(session, message) || messageFactory.isResponse(session, message);
}
从源码可知,只有不是KeepAlive消息时,才将回调下一个Filter的messageReceived函数。
参考文献:
1、http://bbs.youkuaiyun.com/topics/390173203
2、https://my.oschina.net/yjwxh/blog/174633
3、http://blog.youkuaiyun.com/kkk0526/article/details/51732437