欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Netty心跳检测

程序员文章站 2024-03-23 23:03:10
...

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 stub
		this.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 ;
	@Override
	protected void channelRead0(ChannelHandlerContext arg0, Object arg1) throws Exception {
		System.out.println("超时");
		
	}

	@Override
	public 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 总超时)");
	            }
	        }
	}

	@Override
	public 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 stub
		this.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 ;
	@Override
	protected void channelRead0(ChannelHandlerContext arg0, Object arg1) throws Exception {
		System.out.println("超时");
	}
	
	

	@Override
	public void channelRead(ChannelHandlerContext arg0, Object arg1) throws Exception {
		System.out.println("超时");
	}



	@Override
	public 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 总超时)");
	            }
	        }
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		System.out.println("Client active ");
	}
	
	

	
	
	
}