Netty心跳检测

来源:互联网 发布:装饰网络销售要求 编辑:程序博客网 时间:2024/05/17 22:25

Netty心跳检测

网络连接中,处理Idle事件是很常见的,一般情况下,客户端与服务端在指定时间内没有任何读写请求,就会认为连接是idle的。此时,客户端需要向服务端发送ping消息,来维持服务端与客户端的链接。那么怎么判断客户端在指定时间里没有任何读写请求呢?

public class Client {int port;String host;static final int WRITE_WAIT_SECONDS = 5;public Client(int port,String host) {// TODO Auto-generated constructor stubthis.host = host;this.port = port;}public void connect() throws InterruptedException { EventLoopGroup group = new NioEventLoopGroup();          try {              Bootstrap b = new Bootstrap();              b.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(host, port))                      .handler(new ChannelInitializer<SocketChannel>() {                          @Override                          protected void initChannel(SocketChannel ch) throws Exception {                                              ch.pipeline().addLast("decoder", new ObjectDecoder(ClassResolvers.cacheDisabled(this.getClass().getClassLoader())));                        ch.pipeline().addLast("encoder", new ObjectEncoder());                                         ch.pipeline().addLast("ping", new IdleStateHandler(0, WRITE_WAIT_SECONDS, 0,TimeUnit.SECONDS));                        ch.pipeline().addLast(new ClientHandler());                         }                      });              ChannelFuture f = b.connect().sync();              f.channel().closeFuture().sync();          } finally {              group.shutdownGracefully().sync();          }  }public static void main(String[] args) throws CloneNotSupportedException, InterruptedException {Client client = new Client(4456, "127.0.0.1");client.connect();}}
public class ClientHandler extends SimpleChannelInboundHandler<Object>{int unRecPingTimes = 0 ;@Overrideprotected void channelRead0(ChannelHandlerContext arg0, Object arg1) throws Exception {System.out.println("超时");}@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {   if (evt instanceof IdleStateEvent) {            IdleStateEvent event = (IdleStateEvent) evt;            if (event.state() == IdleState.READER_IDLE) {                /*读超时*/                System.out.println("===服务端===(READER_IDLE 读超时)");                if (unRecPingTimes>=3) {ctx.channel().close();} else {unRecPingTimes++;}                                            } else if (event.state() == IdleState.WRITER_IDLE) {                /*写超时*/                   System.out.println("===服务端===(WRITER_IDLE 写超时)");                          } else if (event.state() == IdleState.ALL_IDLE) {                /*总超时*/                System.out.println("===服务端===(ALL_IDLE 总超时)");            }        }}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("client Active()");}}
public class Server {int port;static final int READ_WAIT_SECONDS = 6;public Server(int port) {// TODO Auto-generated constructor stubthis.port = port;}public void start() throws InterruptedException {   EventLoopGroup group = new NioEventLoopGroup();          try {              //create ServerBootstrap instance              ServerBootstrap b = new ServerBootstrap();              //Specifies NIO transport, local socket address              //Adds handler to channel pipeline              b.group(group).channel(NioServerSocketChannel.class).localAddress(port)                      .childHandler(new ChannelInitializer<Channel>() {                          @Override                          protected void initChannel(Channel ch) throws Exception {                         ch.pipeline().addLast("decoder", new ObjectDecoder(ClassResolvers.cacheDisabled(this.getClass().getClassLoader())));                ch.pipeline().addLast("encoder", new ObjectEncoder());                                /*                 * 这里只监听读操作                 * 可以根据需求,监听写操作和总得操作                 */                ch.pipeline().addLast("pong", new IdleStateHandler(READ_WAIT_SECONDS, 0, 0,TimeUnit.SECONDS));                            ch.pipeline().addLast(new EchoServerHandler());                          }                      });              //Binds server, waits for server to close, and releases resources              ChannelFuture f = b.bind().sync();              System.out.println(EchoServer.class.getName() + "started and listen on “" + f.channel().localAddress());              f.channel().closeFuture().sync();          } finally {              group.shutdownGracefully().sync();          }  }public static void main(String[] args) throws InterruptedException {Server server = new Server(4456);server.start();}}
public class ServerHandler extends SimpleChannelInboundHandler<Object>{int unRecPingTimes = 0 ;@Overrideprotected void channelRead0(ChannelHandlerContext arg0, Object arg1) throws Exception {System.out.println("超时");}@Overridepublic void channelRead(ChannelHandlerContext arg0, Object arg1) throws Exception {System.out.println("超时");}@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {  if (evt instanceof IdleStateEvent) {            IdleStateEvent event = (IdleStateEvent) evt;            if (event.state() == IdleState.READER_IDLE) {                /*读超时*/                System.out.println("===服务端===(READER_IDLE 读超时)");                // 失败计数器次数大于等于3次的时候,关闭链接,等待client重连                if (unRecPingTimes>=3) {ctx.channel().close();} else {unRecPingTimes++;}                                           } else if (event.state() == IdleState.WRITER_IDLE) {                /*写超时*/                   System.out.println("===服务端===(WRITER_IDLE 写超时)");            } else if (event.state() == IdleState.ALL_IDLE) {                /*总超时*/                System.out.println("===服务端===(ALL_IDLE 总超时)");            }        }}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.out.println("Client active ");}}