image.png

代码以及分析

虽然handler中有连接断开然后会执行的方法处理,但是有些特殊情况会使连接断开但是服务器并没有感知到,所有加入心跳检测机制可以保证连接的稳定性

Server
  1. public class MyServer {
  2. public static void main(String[] args) {
  3. EventLoopGroup bossGroup = new NioEventLoopGroup(1);
  4. EventLoopGroup workerGroup = new NioEventLoopGroup();
  5. try {
  6. ServerBootstrap serverBootstrap = new ServerBootstrap();
  7. serverBootstrap.group(bossGroup, workerGroup)
  8. .channel(NioServerSocketChannel.class)
  9. .handler(new LoggingHandler(LogLevel.INFO)) //在bossGroup增加一个日志处理器
  10. .childHandler(new ChannelInitializer<SocketChannel>() {
  11. @Override
  12. protected void initChannel(SocketChannel ch) throws Exception {
  13. ChannelPipeline pipeline = ch.pipeline();
  14. //加入netty提供的IdleStateHandler
  15. /*
  16. IdleStateHandler是netty提供的处理空闲状态的处理器
  17. 参数:
  18. long readerIdleTime:表示多长时间没有读,发送心跳检测包,检测是否还处于连接状态
  19. long writerIdleTime:表示多长时间没有写,发送心跳检测包,检测是否还处于连接状态
  20. long allIdleTime:表示多长时间既没有读,也没有写,发送心跳检测包,检测是否还处于连接状态
  21. 当IdleStateHandler触发后,就会传递给管道的下一个handler去处理
  22. 通道调用下一个handler的userEventTriggered方法
  23. */
  24. pipeline.addLast(new IdleStateHandler(3, 5, 7, TimeUnit.SECONDS));
  25. //加入对空闲检测进一步处理的handler
  26. pipeline.addLast(new ServerHandler());
  27. }
  28. });
  29. ChannelFuture channelFuture = serverBootstrap.bind(7000).sync();
  30. channelFuture.channel().closeFuture().sync();
  31. } catch (Exception e) {
  32. e.printStackTrace();
  33. } finally {
  34. bossGroup.shutdownGracefully();
  35. workerGroup.shutdownGracefully();
  36. }
  37. }
  38. }

Handler
  1. public class ServerHandler extends ChannelInboundHandlerAdapter {
  2. /**
  3. * @param ctx 上下文
  4. * @param evt 事件
  5. * @throws Exception
  6. */
  7. @Override
  8. public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
  9. if (evt instanceof IdleStateEvent) {
  10. IdleStateEvent event = (IdleStateEvent) evt;
  11. String eventType = "";
  12. switch (event.state()) {
  13. case READER_IDLE:
  14. eventType = "读空闲";
  15. break;
  16. case WRITER_IDLE:
  17. eventType = "写空闲";
  18. break;
  19. case ALL_IDLE:
  20. eventType = "读写空闲";
  21. break;
  22. }
  23. System.out.println(ctx.channel().remoteAddress() + "---超时事件发生:" + eventType);
  24. System.out.println("服务器做出相应的处理");
  25. }
  26. }
  27. }