netty学习四:监听channel的读写空闲情况

来源:互联网 发布:js点击隐藏按钮 编辑:程序博客网 时间:2024/06/06 05:15

概述


netty提供了一个IdleStateHandler类,可以用监听channel的读写空闲状态。构造方法如下:

 public IdleStateHandler(long readerIdleTime, long writerIdleTime, long allIdleTime,TimeUnit unit) { }

1、当隔了readerIdleTime后,如果客户端未发送信息到服务端,那么会触发channel的读空闲。
2、当隔了writerIdleTime后,如果服务端未发送信息到客户端,那么会触发channel的写空闲。


服务端代码


package idle.server;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.logging.LogLevel;import io.netty.handler.logging.LoggingHandler;public class ChannelIdleServer {    public static void main(String[] args) throws InterruptedException {        // 接收连接,但是不处理        EventLoopGroup parentGroup = new NioEventLoopGroup();        // 真正处理连接的group        EventLoopGroup childGroup = new NioEventLoopGroup();        try {            //加载Initializer            ServerBootstrap serverBootstrap = new ServerBootstrap();            serverBootstrap.group(parentGroup, childGroup)                           .channel(NioServerSocketChannel.class)                           .handler(new  LoggingHandler(LogLevel.INFO))                           //这里的childHandler是服务于childGroup的,如果直接使用                           //handler方法添加处理器,则是服务于parentGroup的                           .childHandler(new ChannelIdleServerInitializer());            //绑定监听端口            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();            channelFuture.channel().closeFuture().sync();        }        finally {            parentGroup.shutdownGracefully();            childGroup.shutdownGracefully();        }    }}package idle.server;import java.util.concurrent.TimeUnit;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.socket.SocketChannel;import io.netty.handler.timeout.IdleStateHandler;public class ChannelIdleServerInitializer extends ChannelInitializer<SocketChannel>{    @Override    protected void initChannel(SocketChannel ch) throws Exception {        ChannelPipeline pipeline = ch.pipeline();        pipeline.addLast(new IdleStateHandler(5, 7, 20,TimeUnit.SECONDS));        pipeline.addLast(new ChannelIdleServerHandler());    }}package idle.server;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;import io.netty.handler.timeout.IdleStateEvent;public class ChannelIdleServerHandler extends ChannelInboundHandlerAdapter{    @Override    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {        if (evt instanceof IdleStateEvent) {            IdleStateEvent idleStateEvent = (IdleStateEvent)evt;            String eventType = null;            switch (idleStateEvent.state()) {            case READER_IDLE:                eventType = "读空闲";                break;            case WRITER_IDLE:                eventType = "写空闲";                break;            case ALL_IDLE:                eventType = "读写空闲";                break;            }            System.out.println(ctx.channel().remoteAddress() + "超时事件:" + eventType);            ctx.channel().close();        }    }}

客户端代码


package idle.client;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import io.netty.bootstrap.Bootstrap;import io.netty.channel.Channel;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioSocketChannel;public class ChannelIdleClient {    public static void main(String[] args) throws InterruptedException, IOException {        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();        try {            //加载Initializer            Bootstrap bootstrap = new Bootstrap();            bootstrap.group(eventLoopGroup)                           .channel(NioSocketChannel.class)                           .handler(new ChannelIdleInitializer());            //连接服务端            Channel channel = bootstrap.connect("localhost", 8899).sync().channel();            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));            for(;;) {                channel.writeAndFlush(br.readLine() + "\r\n");            }        }        finally {            eventLoopGroup.shutdownGracefully();        }    }}package idle.client;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.DelimiterBasedFrameDecoder;import io.netty.handler.codec.Delimiters;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.codec.string.StringEncoder;import io.netty.util.CharsetUtil;public class ChannelIdleInitializer extends ChannelInitializer<SocketChannel>{    @Override    protected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();        //1、按照分隔符切割消息        pipeline.addLast(new DelimiterBasedFrameDecoder(4096,Delimiters.lineDelimiter()));        //2、socket编程中需要对字符串进行编码解码        pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));        pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));        //3、添加自定义处理器        pipeline.addLast(new ChannelIdleClientHandler());    }}package idle.client;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;public class ChannelIdleClientHandler extends SimpleChannelInboundHandler<String>{    @Override    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {        System.out.println(msg);    }}

可以利用这种机制来实现心跳,检测服务器是否挂掉了。


csdn code 路径


这个项目的源代码放置在csdn code上,欢迎访问。

netty_study

原创粉丝点击