mina作为NIO的封装,还是很优秀的,自身提供池的服务,以至于你可以专注你的业务,不需要担心底层socket问题。所以我在使用mina以后,真的就不关心底层的东西了,结果在使用后发现 server或者client 会在另一端停止后抛出一些异常,我允许你因为对端挂了抛出异常,但是你告诉我怎么正常停止mina呀!要不然server端的端口不释放,总会发生地址占用的啊。
查了好多资料后,终于发现一个关键点:dispose。这个方法才是正常停止mina的最佳选择。我曾企图通过ioSession来停止,但总有问题。虽然dispose方法调用后确实稳定的停止了mina(那端要停止,那端调用),但是调用端需要知道此时通道已经没有数据传输了,否则你随意调用dispose可能发生异常。于是你还要配置一个地方,session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 15); 指定多久以后通道没用就视为IDLE状态。这里我直接配置为both_idle,其他两种没试过,因为我认为需要停止时,读写通道都要空闲(或者说通道上没有读、写)才可以。最后再测试,果然稳定的停止了。
总结如下(红色部分):
1、配置ioSession的idle时间;
public void sessionOpened(IoSession session) throws Exception {
//when client need to shutdown, this will control waiting time before all data send and shutdown successfully.
session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 15);
session.setAttribute(Configure.cfg.KEYISALIVE, true);
setIoSession(session);
}
2、判断是否idle,在idle时调用dispose停止。
public void release(){
if(isHaveSession()){
clientHandler.getIoSession().setAttribute(Configure.cfg.KEYISALIVE, false);
while( ! clientHandler.getIoSession().isIdle(IdleStatus.BOTH_IDLE)
&& clientHandler.getIoSession().isConnected() ){
try {
Thread.sleep(Configure.cfg.THREAD_SLEEP);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
connector.dispose();
client.isAlive = false;
}