当前位置:   article > 正文

Netty-心跳与空闲检测_netty websocket 心跳仍然读空闲

netty websocket 心跳仍然读空闲
  • 网络问题 

连接假死的现象是:在某一端(服务端或者客户端)看来,底层的 TCP 连接已经断开了,但是应用程序并没有捕获到,因此会认为这条连接仍然是存在的,从 TCP 层面来说,只有收到四次握手数据包或者一个 RST 数据包,连接的状态才表示已断开。

  •  空闲检测写法一:

服务端:只需要检测一段时间内,是否收到过客户端发来的数据即可,Netty 自带的 IdleStateHandler 就可以实现这个功能。

  1. public class MyIdleStateHandler extends IdleStateHandler {
  2. public MyIdleStateHandler() {
  3. super(5, 0, 0, TimeUnit.SECONDS);
  4. }
  5. @Override
  6. protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {
  7. System.out.println( "5秒内未读到数据,关闭连接");
  8. ctx.channel().close();
  9. }
  10. }
  1. 其中第一个表示读空闲时间,指的是在这段时间内如果没有数据读到,就表示连接假死;第二个是写空闲时间,指的是 在这段时间如果没有写数据,就表示连接假死;第三个参数是读写空闲时间,表示在这段时间内如果没有产生数据读或者写,就表示连接假死。写空闲和读写空闲为0,表示我们不关心者两类条件;最后一个参数表示时间单位。
  2. 连接假死之后会回调 channelIdle() 方法,在这个方法里面打印消息,并手动关闭连接。

客户端:定时发心跳

  1. public class HeartBeatTimerHandler extends ChannelInboundHandlerAdapter {
  2. @Override
  3. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  4. //定时发送心跳包
  5. scheduleSendHeartBeat(ctx);
  6. super.channelActive(ctx);
  7. }
  8. private void scheduleSendHeartBeat(ChannelHandlerContext ctx) {
  9. ByteBuf byteBuf=ctx.alloc().buffer();
  10. byteBuf.writeByte(1);
  11. ctx.executor().schedule(() -> {
  12. if (ctx.channel().isActive()) {
  13. ctx.writeAndFlush(byteBuf);
  14. scheduleSendHeartBeat(ctx);
  15. }
  16. }, 2, TimeUnit.SECONDS);
  17. }
  18. }

客户端空闲检测:只需要检测一段时间内,是否收到过服务端回复的数据即可,同服务器空闲检测(略)

服务端回复心跳:给客户端回复心跳(略)


  • 空闲检测写法二:

给连接加处理器:空闲检测处理器会调用下一个处理器的userEventTriggered()方法 

  1. .childHandler(new ChannelInitializer<SocketChannel>() {
  2. @Override
  3. protected void initChannel(SocketChannel ch) throws Exception {
  4. //空闲检测,会调用下一个处理器的userEventTriggered()方法执行
  5. ch.pipeline().addLast(new IdleStateHandler(10,0,0));
  6. ch.pipeline().addLast(new MyPongWebSocketFrame());
  7. }
  8. });

下一个处理器,重写userEventTriggered()方法

  1. import io.netty.channel.ChannelHandlerContext;
  2. import io.netty.channel.SimpleChannelInboundHandler;
  3. import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
  4. import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
  5. import io.netty.handler.timeout.IdleStateEvent;
  6. public class MyPongWebSocketFrame extends SimpleChannelInboundHandler<PongWebSocketFrame> {
  7. //用户事件触发的时候(如空闲检测)
  8. @Override
  9. public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
  10. if(evt instanceof IdleStateEvent) {
  11. IdleStateEvent event= (IdleStateEvent) evt;
  12. System.out.println("MyPongWebSocketFrame userEventTriggered:" + event.state());
  13. ctx.channel().writeAndFlush(new PingWebSocketFrame());
  14. }
  15. }
  16. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/242172
推荐阅读
相关标签
  

闽ICP备14008679号