文档章节

netty中使用IdleStateHandler来发起心跳

mn_1127
 mn_1127
发布于 2015/07/07 15:24
字数 865
阅读 4032
收藏 11

网络连接中,处理Idle事件是很常见的,一般情况下,客户端与服务端在指定时间内没有任何读写请求,就会认为连接是idle的。此时,客户端需要向服务端发送ping消息,来维持服务端与客户端的链接。那么怎么判断客户端在指定时间里没有任何读写请求呢?netty中为我们提供一个特别好用的IdleStateHandler来干这个苦差事!请看下面代码:

public class EchoClient {
	private final static int readerIdleTimeSeconds = 40;//读操作空闲30秒
	private final static int writerIdleTimeSeconds = 50;//写操作空闲60秒
	private final static int allIdleTimeSeconds = 100;//读写全部空闲100秒
    public void connect(int port, String host) throws Exception {
	// 配置客户端NIO线程组
	EventLoopGroup group = new NioEventLoopGroup();
	try {
	    Bootstrap b = new Bootstrap();
	    b.group(group).channel(NioSocketChannel.class)
		    .option(ChannelOption.TCP_NODELAY, true)
		    .handler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch)
					throws Exception {
				    ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
				    ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(readerIdleTimeSeconds, writerIdleTimeSeconds,allIdleTimeSeconds));
				    ch.pipeline().addLast( new DelimiterBasedFrameDecoder(1024, delimiter));
				    ch.pipeline().addLast(new StringDecoder());
				    ch.pipeline().addLast(new EchoClientHandler());
				}
		    });

	    // 发起异步连接操作
	    ChannelFuture f = b.connect(host, port).sync();
	    // 当代客户端链路关闭
	    f.channel().closeFuture().sync();
	} finally {
	    // 优雅退出,释放NIO线程组
	    group.shutdownGracefully();
	}
    }

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
	int port = 8080;
	if (args != null && args.length > 0) {
	    try {
		port = Integer.valueOf(args[0]);
	    } catch (NumberFormatException e) {
		// 采用默认值
	    }
	}
	new EchoClient().connect(port, "127.0.0.1");
    }
}

在netty的客户端中添加:

ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(readerIdleTimeSeconds, writerIdleTimeSeconds,allIdleTimeSeconds));

这个处理器,它的作用就是用来检测客户端的读取超时的,该类的第一个参数是指定读操作空闲秒数,第二个参数是指定写操作的空闲秒数,第三个参数是指定读写空闲秒数,当有操作操作超出指定空闲秒数时,便会触发UserEventTriggered事件。所以我们只需要在自己的handler中截获该事件,然后发起相应的操作即可(比如说发起ping操作)。以下是我们自定义的handler中的代码:

public class EchoClientHandler extends ChannelHandlerAdapter {

	private int counter;
	static final String ECHO_REQ = "Hi, Lilinfeng. Welcome to Netty.$_";

	public EchoClientHandler() {
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) {
		for (int i = 0; i < 10; i++) {
			ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes()));
		}
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
		System.out.println("This is " + ++counter + " times receive server : [" + msg + "]");
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		cause.printStackTrace();
		ctx.close();
	}

	@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");
		}
	}

这里,我们重点看重新的 userEventTriggered方法:

        首先,判断evt事件是不是IdleStateEvent事件;

        然后,继续判断是读空闲事件还是写空闲事件还是读写空闲事件;

        最后,根据不同事件类型发起相应的操作


好了,现在回到我们的主题,我们的目的是在客户端在写空闲超时时,客户端主动发起一次平操作,所以我们只需要判断写空闲超时,发起ping操作即可!


© 著作权归作者所有

共有 人打赏支持
mn_1127
粉丝 7
博文 23
码字总数 6952
作品 0
杭州
后端工程师
私信 提问
加载中

评论(2)

mn_1127
mn_1127

引用来自“cyb_beta”的评论

可以的话分析下 IdleStateHandler的源码,就知道为什么要重写userEventTriggered方法
感谢关注!我对netty也是学习,还没有在实践中应用过。你对源码熟悉的话,可以给大家分析一下!
cyb_beta
cyb_beta
可以的话分析下 IdleStateHandler的源码,就知道为什么要重写userEventTriggered方法
Netty 那些事儿 ——— 心跳机制

本文是Netty文集中“Netty 那些事儿”系列的文章。主要结合在开发实战中,我们遇到的一些“奇奇怪怪”的问题,以及如何正确且更好的使用Netty框架,并会对Netty中涉及的重要设计理念进行介绍...

tomas家的小拨浪鼓
2017/11/11
0
0
Netty 超时机制及心跳程序实现

本文同步至 本文介绍了 Netty 超时机制的原理,以及如何在连接闲置时发送一个心跳来维持连接。 Netty 超时机制的介绍 Netty 的超时类型 IdleState 主要分为: ALL_IDLE : 一段时间内没有数据...

waylau
2015/11/06
0
0
从零开始学netty——心跳检测

通过学习前面的内容,大家基本可以使用netty来开发程序了,本文再补充一下心跳检测部分,属于是完善功能的内容了。 为什么要有心跳检测 大部分人听到心跳连接这个名词都是在数据库连接池上,...

xpbob
2018/05/20
0
0
Netty(一) SpringBoot 整合长连接心跳机制

前言 Netty 是一个高性能的 NIO 网络框架,本文基于 SpringBoot 以常见的心跳机制来认识 Netty。 最终能达到的效果: 客户端每隔 N 秒检测是否需要发送心跳。 服务端也每隔 N 秒检测是否需要...

crossoverJie
2018/05/28
0
0
Netty 心跳服务之 IdleStateHandler 源码分析

前言:Netty 提供的心跳介绍 Netty 作为一个网络框架,提供了诸多功能,比如我们之前说的编解码,Netty 准备很多现成的编解码,同时,Netty 还为我们准备了网络中,非常重要的一个服务-----...

tantexian
03/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

租房软件隐私保护如同虚设

近日,苏州市民赵先生向江苏新闻广播新闻热线025-84658888反映,他在“安居客”手机应用软件上浏览二手房信息,并且使用该软件自动生成的虚拟号码向当地一家中介公司进行咨询。可电话刚挂不久...

linux-tao
今天
1
0
分布式项目(五)iot-pgsql

书接上回,在Mapping server中,我们已经把数据都整理好了,现在利用postgresql存储历史数据。 iot-pgsql 构建iot-pgsql模块,这里我们写数据库为了性能考虑不在使用mybatis,换成spring jd...

lelinked
今天
4
0
一文分析java基础面试题中易出错考点

前言 这篇文章主要针对的是笔试题中出现的通过查看代码执行结果选择正确答案题材。 正式进入题目内容: 1、(单选题)下面代码的输出结果是什么? public class Base { private Strin...

一看就喷亏的小猿
今天
2
0
cocoapods 用法

cocoapods install pod install 更新本地已经install的仓库 更新所有的仓库 pod update --verbose --no-repo-update 更新制定的仓库 pod update ** --verbose --no-repo-update...

HOrange
今天
3
0
linux下socket编程实现一个服务器连接多个客户端

使用socekt通信一般步骤 1)服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept()等待客户端连接。 2)客户端:socker()建立套接字,连接(connect)服务器,连接上后...

shzwork
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部