netty心跳机制以及断线重连
心跳机制
使用IdleStateHandler来实现心跳,Client端连接到Server端后,会循环执行一个任务:随机等待几秒,然后ping一下Server端,即发送一个心跳包。当等待的时间超过规定时间,将会发送失败,以为Server端在此之前已经主动断开连接了。
服务端; 心跳对于服务端,就是清除闲置会话
/**
- 空闲次数
/
private int idle_count = 1;
/* - 发送次数
/
private int count = 1;
/* - 超时处理,如果5秒没有收到客户端的心跳,就触发; 如果超过两次,则直接关闭;
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {
if (obj instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) obj;
if (IdleState.READER_IDLE.equals(event.state())) { // 如果读通道处于空闲状态,说明没有接收到心跳命令
if (idle_count > 2) {
System.out.println("超过两次无客户端请求,关闭该channel");
ctx.channel().close().sync();
}
System.out.println("已等待5秒还没收到客户端发来的消息");
idle_count++;
}
} else {
super.userEventTriggered(ctx, obj);
}
断线重连
断线重连实现也很简单,就是给通道加上一个断线重连的监听器ChannelFutureListene,该监听器如果监听到与服务端的连接断开了就会每隔1s触发一次重连操作,担忧一个问题需要注意的是 ChannelFuture f = b.connect(host,port);不能加sync()也就是不能写成 ChannelFuture f = b.connect(host,port).sync();不然重连操作无法触发,我也不知道为啥。。。。还有就是不能有任何关闭通道的代码,也就是group.shutdownGracefully(); 不然断线重连无效,因为你已经把该通道关闭了。
心跳对于客户端,检测会话是否断开,是否重连,检测网络延时
//连接服务器
ChannelFuture future = client.connect("localhost", 7001).sync();
//断线重连的监听器ChannelFutureListener
future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (!channelFuture.isSuccess()) {
final EventLoop loop = channelFuture.channel().eventLoop();
loop.schedule(new Runnable() {
@Override
public void run() {
log.error("服务端链接不上,开始重连操作...");
System.err.println("服务端链接不上,开始重连操作...");
// start(); //进行重连操作
}
}, 1L, TimeUnit.SECONDS);
} else {
channel = channelFuture.channel();
log.info("服务端链接成功...");
System.err.println("服务端链接成功...");
}
}
});