天天看點

Netty中的Idle事件

Netty中的Idle事件

網絡連接配接中,處理Idle事件是很常見的,比如在mqtt服務中,用戶端與服務端在指定時間内沒有任何讀寫請求,就會認為連接配接是idle的,此時,用戶端在指定的idle時間内沒有向服務端發送ping消息,服務端可以斷開與用戶端的連結。

下面的代碼示範了在netty中如何設定idle事件。

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;


public class NettyTest {

	public static void main(String[] args) throws InterruptedException {
	    EventLoopGroup bossGroup = new NioEventLoopGroup(); 
	    EventLoopGroup workerGroup = new NioEventLoopGroup();
	    try {
	        ServerBootstrap b = new ServerBootstrap();
	        b.group(bossGroup, workerGroup)
	         .channel(NioServerSocketChannel.class)
	         .childHandler(new ChannelInitializer<SocketChannel>() {
	        	private static final int IDEL_TIME_OUT = 10;
	            private static final int READ_IDEL_TIME_OUT = 4;
	        	private static final int WRITE_IDEL_TIME_OUT = 5;
	
	             @Override
	             public void initChannel(SocketChannel ch) throws Exception {
	         		ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(READ_IDEL_TIME_OUT, WRITE_IDEL_TIME_OUT, IDEL_TIME_OUT));
	                ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){
	                	@Override
	                	public void userEventTriggered(
	                			ChannelHandlerContext ctx, Object evt)
	                			throws Exception {
	                		if(IdleStateEvent.class.isAssignableFrom(evt.getClass())){
	                			IdleStateEvent event = (IdleStateEvent) evt;
	                			if(event.state() == IdleState.READER_IDLE)
	                				System.out.println("read idle");
	                			else if(event.state() == IdleState.WRITER_IDLE)
	                				System.out.println("write idle");
	                			else if(event.state() == IdleState.ALL_IDLE)
	                				System.out.println("all idle");
	                		}
	                	}
	                });
	             }
	         })
	         .option(ChannelOption.SO_BACKLOG, 128)
	         .childOption(ChannelOption.SO_KEEPALIVE, true);
	        
	        ChannelFuture f = b.bind(8080).sync();
	        f.channel().closeFuture().sync();
	    } finally {
	        workerGroup.shutdownGracefully();
	        bossGroup.shutdownGracefully();
	    }
	}
	
}
           

首先添加了idleStateHandler用于監聽連結idle,如果連接配接到達idle時間,這個handler會觸發idleEvent,之後通過重寫userEventTriggered方法,完成idle事件的處理。

可以用telnet進行測試:

telnet 127.0.0.1 8080

測試結果:

read idle

write idle

read idle

all idle

write idle

read idle

write idle

read idle