服务端代码
public class MyServer { /** 30秒后超时 */ private static final int IDELTIMEOUT = 30; /** 15秒发送一次心跳包 */ private static final int HEARTBEATRATE = 15; /** 心跳包内容 */ private static final String HEARTBEATREQUEST = "xixixi";//预设请求内容 private static final String HEARTBEATRESPONSE = "hahaha";//预设应答内容(记得客户端在接收到预设请求内容回复给服务端一定也是这个内容哦) public static void main(String[] args) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getSessionConfig().setReadBufferSize(2048); acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, IDELTIMEOUT); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); // acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory())); acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory())); //心跳检测开始 KeepAliveMessageFactory heartBeatFactory = new KeepAliveMessageFactoryImpl(); KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory, IdleStatus.BOTH_IDLE); //设置是否forward到下一个filter heartBeat.setForwardEvent(true); //设置心跳频率 heartBeat.setRequestInterval(HEARTBEATRATE); //设置失败处理handler heartBeat.setRequestTimeoutHandler(new KeepAliveRequestTimeoutHandlerImpl()); acceptor.getFilterChain().addLast("heartbeat", heartBeat); //心跳检测结束 acceptor.setHandler(new MyIoHandler()); acceptor.bind(new InetSocketAddress(9123)); System.out.println("Server started on port:9123" ); } private static class KeepAliveMessageFactoryImpl implements KeepAliveMessageFactory { @Override public boolean isRequest(IoSession ioSession, Object o) { System.out.print("服务端判断消息是否为请求包消息: "+o); if (o.equals(HEARTBEATREQUEST)) return true; return false; } @Override public boolean isResponse(IoSession session, Object message) { System.out.print("服务端判断响应心跳包信息: " + message); if(message.equals(HEARTBEATRESPONSE)) return true; return false; } @Override public Object getRequest(IoSession session) { System.out.print("服务端发送给客户端的心跳包消息: " + HEARTBEATREQUEST); return HEARTBEATREQUEST; } @Override public Object getResponse(IoSession session, Object request) { System.out.print("响应预设信息: " + HEARTBEATRESPONSE); return HEARTBEATRESPONSE; // return null; } } private static class KeepAliveRequestTimeoutHandlerImpl implements KeepAliveRequestTimeoutHandler{ @Override public void keepAliveRequestTimedOut(KeepAliveFilter keepAliveFilter, IoSession ioSession) throws Exception { ioSession.close(true); System.out.print("客户端挂了 我把session给干掉了!"); } } }
客户端代码(在这里只提供客户端handler部分)
/** 心跳包内容 */ private static final String HEARTBEATREQUEST = "xixixi"; private static final String HEARTBEATRESPONSE = "hahaha"; @Override public void messageReceived(IoSession ioSession, Object o) throws Exception { String s = o.toString(); if(o.equals(HEARTBEATREQUEST)){ ioSession.write(HEARTBEATRESPONSE); } }这里简述一下心跳检测的过程,mina在一定时间内发现客户端与服务端没有通信的情况下会调用KeepAliveFilter里面的sessionIdle方法来获取空闲时预设的发送给客户端的消息,然后发送给客户端,客户端接收到消息后恢复给服务端预设响应的消息,服务端收到消息并判断是否为预设定的响应消息,如果是的话就证明客户端活着,如果长时间收不到消息活着收到的消息不是预设定的响应消息后就会调用KeepAliveRequestTimeOutHandler接口里面的keepAliveRequestAliveTimedOut方法(在这个方法里就可以实现自己的业务需求,记得在这个方法里面要把session关掉,不然服务端一直发送检测心跳的消息)。
以上均是自己的理解,如有理解不正确的地方请指正,互相进步,谢谢