赞
踩
连接假死的现象是:在某一端(服务端或者客户端)看来,底层的 TCP 连接已经断开了,但是应用程序并没有捕获到,因此会认为这条连接仍然是存在的,从 TCP 层面来说,只有收到四次握手数据包或者一个 RST 数据包,连接的状态才表示已断开。
服务端:只需要检测一段时间内,是否收到过客户端发来的数据即可,Netty 自带的
IdleStateHandler
就可以实现这个功能。
public class MyIdleStateHandler extends IdleStateHandler { public MyIdleStateHandler() { super(5, 0, 0, TimeUnit.SECONDS); } @Override protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception { System.out.println( "5秒内未读到数据,关闭连接"); ctx.channel().close(); } }
- 其中第一个表示读空闲时间,指的是在这段时间内如果没有数据读到,就表示连接假死;第二个是写空闲时间,指的是 在这段时间如果没有写数据,就表示连接假死;第三个参数是读写空闲时间,表示在这段时间内如果没有产生数据读或者写,就表示连接假死。写空闲和读写空闲为0,表示我们不关心者两类条件;最后一个参数表示时间单位。
- 连接假死之后会回调
channelIdle()
方法,在这个方法里面打印消息,并手动关闭连接。客户端:定时发心跳
public class HeartBeatTimerHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { //定时发送心跳包 scheduleSendHeartBeat(ctx); super.channelActive(ctx); } private void scheduleSendHeartBeat(ChannelHandlerContext ctx) { ByteBuf byteBuf=ctx.alloc().buffer(); byteBuf.writeByte(1); ctx.executor().schedule(() -> { if (ctx.channel().isActive()) { ctx.writeAndFlush(byteBuf); scheduleSendHeartBeat(ctx); } }, 2, TimeUnit.SECONDS); } }客户端空闲检测:只需要检测一段时间内,是否收到过服务端回复的数据即可,同服务器空闲检测(略)
服务端回复心跳:给客户端回复心跳(略)
给连接加处理器:空闲检测处理器会调用下一个处理器的userEventTriggered()方法
.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //空闲检测,会调用下一个处理器的userEventTriggered()方法执行 ch.pipeline().addLast(new IdleStateHandler(10,0,0)); ch.pipeline().addLast(new MyPongWebSocketFrame()); } });
下一个处理器,重写userEventTriggered()方法
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.SimpleChannelInboundHandler;
- import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
- import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
- import io.netty.handler.timeout.IdleStateEvent;
-
- public class MyPongWebSocketFrame extends SimpleChannelInboundHandler<PongWebSocketFrame> {
- //用户事件触发的时候(如空闲检测)
- @Override
- public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
- if(evt instanceof IdleStateEvent) {
- IdleStateEvent event= (IdleStateEvent) evt;
- System.out.println("MyPongWebSocketFrame userEventTriggered:" + event.state());
- ctx.channel().writeAndFlush(new PingWebSocketFrame());
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。