Netty心跳检测代码及源码流程
心跳检测是指在TCP长连接中,客户端和服务端定时发送和接受简单数据,确保服务正常,在Netty中,对心跳检测进行了很好的封装,下面我们来看一下心跳检测的实现和源码
Netty通过什么来实现心跳?
IdleStateHandler:Netty是通过IdleStateHandler来实现心跳检测的。
怎么使用?
客户端
public class HeartBeatClient {public static void main(String[] args) throws Exception {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap bootstrap = new Bootstrap();bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();//加入解码器,接受新的信息时触发pipeline.addLast(new StringDecoder());//加入编码器,当发出信息时候进行编码后再发出pipeline.addLast(new StringEncoder());//加入客服端的业务处理器pipeline.addLast(new HeartBeatClientHandler());}});System.out.println("netty client start。。");//同步连接服务端ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9000).sync();Channel channel = channelFuture.channel();while (channel.isActive()) {//每两秒发一次心跳检测Thread.sleep(2000);
// 每四秒进行一次心跳检测
// Thread.sleep(4000);channel.writeAndFlush("心跳检测");}} finally {group.shutdownGracefully();}}
}public class HeartBeatClientHandler extends SimpleChannelInboundHandler<String> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {System.out.println(" client received :" + msg);if (msg != null && msg.equals("服务端关闭连接")) {System.out.println(" 服务端关闭连接,客户端也关闭");ctx.channel().closeFuture();}}
}
服务端
public class HeartBeatServer {public static void main(String[] args) throws Exception {//接受连接线程池EventLoopGroup bossGroup = new NioEventLoopGroup(1);//处理业务线程池,默认是cpu凉杯EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();//加入解码器,接受新的信息时触发pipeline.addLast(new StringDecoder());//加入编码器,当发出信息时候进行编码后再发出pipeline.addLast(new StringEncoder());//加入心跳检测处理器// readerIdleTime 读超时时间// writerIdleTime 写超时时间// allIdleTime 总的超时时间pipeline.addLast(new IdleStateHandler(3, 0, 0, TimeUnit.SECONDS));//加入服务端的业务处理器pipeline.addLast(new HeartBeatServerHandler());}});System.out.println("netty server start。。");//ChannelFuture channelFuture = serverBootstrap.bind(9000).sync();channelFuture.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}public class HeartBeatServerHandler extends SimpleChannelInboundHandler<String> {int readIdleTimes = 0;@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {System.out.println(" ====== > [server] message received : " + msg);if ("心跳检测".equals(msg)) {ctx.channel().writeAndFlush("Heath ok");} else {System.out.println(" 其他信息处理 ... ");}}/*** netty将超时的事务逻辑交由用户自己处理* @param ctx* @param evt* @throws Exception*/@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {IdleStateEvent event = (IdleStateEvent) evt;String eventType = null;switch (event.state()) {case READER_IDLE:eventType = "读空闲";readIdleTimes++; // 读空闲的计数加1break;case WRITER_IDLE:eventType = "写空闲";// 不处理break;case ALL_IDLE:eventType = "读写空闲";// 不处理break;}System.out.println(ctx.channel().remoteAddress() + "超时事件:" + eventType);if (readIdleTimes > 3) {System.out.println(" [server]读空闲超过3次,关闭连接,释放更多资源");ctx.channel().writeAndFlush("服务端关闭连接");ctx.channel().close();}}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {System.err.println("=== " + ctx.channel().remoteAddress() + " is active ===");}
}
IdleStateHandler源码
构造方法
public IdleStateHandler(long readerIdleTime, long writerIdleTime, long allIdleTime,TimeUnit unit) {this(false, readerIdleTime, writerIdleTime, allIdleTime, unit);}
构造方法没什么特别,主要是对其中一些属性赋值。
channelActive方法
@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {// This method will be invoked only if this handler was added// before channelActive() event is fired. If a user adds this handler// after the channelActive() event, initialize() will be called by beforeAdd().initialize(ctx); //进入查看源码super.channelActive(ctx);}
channelActive中有个initialize(ctx)方法,看一下这个方法
private void initialize(ChannelHandlerContext ctx) {// Avoid the case where destroy() is called before scheduling timeouts.// See: https://github.com/netty/netty/issues/143switch (state) {case 1:case 2:return;}state = 1;initOutputChanged(ctx);lastReadTime = lastWriteTime = ticksInNanos(); //当前时间if (readerIdleTimeNanos > 0) { //读超时时间readerIdleTimeout = schedule(ctx, new ReaderIdleTimeoutTask(ctx),readerIdleTimeNanos, TimeUnit.NANOSECONDS);}if (writerIdleTimeNanos > 0) {writerIdleTimeout = schedule(ctx, new WriterIdleTimeoutTask(ctx),writerIdleTimeNanos, TimeUnit.NANOSECONDS);}if (allIdleTimeNanos > 0) {allIdleTimeout = schedule(ctx, new AllIdleTimeoutTask(ctx),allIdleTimeNanos, TimeUnit.NANOSECONDS);}}
initialize(ctx)方法主要是对一些属性赋值和判断是否要进行读,写等超时的定时方法,因为我们是测试读超时,那么我们看一下ReaderIdleTimeoutTask的run方法
@Overrideprotected void run(ChannelHandlerContext ctx) {long nextDelay = readerIdleTimeNanos;if (!reading) { //获取是否超时 nextDelay<0 超时 nextDelay>0则不超时nextDelay -= ticksInNanos() - lastReadTime;}if (nextDelay <= 0) {// Reader is idle - set a new timeout and notify the callback.readerIdleTimeout = schedule(ctx, this, readerIdleTimeNanos, TimeUnit.NANOSECONDS);boolean first = firstReaderIdleEvent;firstReaderIdleEvent = false;try {IdleStateEvent event = newIdleStateEvent(IdleState.READER_IDLE, first);channelIdle(ctx, event); //交给自己实现的userEventTriggered进行处理} catch (Throwable t) {ctx.fireExceptionCaught(t);}} else {// Read occurred before the timeout - set a new timeout with shorter delay. 没超时,则再次调用schedule()方法readerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);}}
这里首先会判断是否以前超过了预订的超时时间,若没超时,则将赋值剩余超时时间,继续调用本方法,若超时,则调用我们自己实现的userEventTriggered()方法处理业务逻辑
流程图
Netty心跳检测代码及源码流程相关推荐
- 视频教程-物联网之java实现(springboot + netty + 心跳,附完整源码)-Java
物联网之java实现(springboot + netty + 心跳,附完整源码) 10年的软件行业从业经验,熟悉java开发.java 架构.微服务.自动化高级运维.压力测试等. 林忠明 ¥200. ...
- Netty(八) Netty心跳检测机制
1.什么是长链接和短链接 在HTTP/1.0中默认使用短连接.也就是说,客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接.当客户端浏览器访问的某个HTML或其他类型的Web页中 ...
- Netty心跳检测机制
一.Netty心跳检测机制 心跳:即在 TCP 长连接中,客户端和服务器之间定期发送的一种特殊的数据包,通知对方自己还在线,以确保 TCP 连接的有效性. 在 Netty 中,实现心跳机制的关键是 I ...
- 目标检测之DarkNet-DarkNet源码解读<一>测试篇
目标检测-DarkNet源码解读 DarkNet源码解读 1.一些思考 1.1 DarkNet的本质 1.2 深度学习分为两条线 1.3 检测任务的步骤 2.代码走读 2.1 程序入口 2. ...
- Python基于CRNN&CTPN的文本检测系统(源码&教程)
1.背景 文本是人类最伟大和最具影响力的发明之一,是人类智慧的结晶,是人类文化.思想传承的一种基本的表达方式和不可或缺的载体.在21世纪,文本与日常生活密切相关.描述.理解万事万物,表达情感,与他人交 ...
- Node后端模板代码(附源码)
前言 之前也写过简单的node服务器代码,但不算做事一个工程,这一次因为也需求,就写了这套后端模板. 从git上找的一些node模板,功能是可以实现,但工作流程理解起来有点困难,可能是小弟我水平有限, ...
- 【Matlab瑕疵检测】阙值瓶盖瑕疵检测【含源码 730期】
一.代码运行视频(哔哩哔哩) [Matlab瑕疵检测]阙值瓶盖瑕疵检测[含源码 730期] 二.matlab版本及参考文献 1 matlab版本 2014a 2 参考文献 [1] 蔡利梅.MATLAB ...
- Netty -Netty心跳检测机制案例,Netty通过WebSocket编程实现服务器和客户端长链接
Netty心跳检测机制案例 案例要求 编写一个Netty心跳检测机制案例,当服务器超过3秒没有读时,就提示读空闲 当服务器超过5秒没有写操作时,提示写空闲 服务器超过7秒没有读或者写操作时,就提示读写 ...
- 基于Opencv的车距检测系统(源码&教程)
1.研究背景 对本车前方车辆的识别及距离检测是计算机视觉技术在智能网联汽车中的一个重要内容.要想在错综繁杂的交通环境中实现无人驾驶,对行车环境中其他车辆信息的获取是十分重要的.因此,对本车前方车辆的识 ...
最新文章
- double java 坑,Java中四则运算的那些坑
- python中if错误-python中的异常处理
- View工作原理(一)事件传递原理详解
- DayDayUp:那些属于程序猿江湖的鄙视链(看完别笑^~^,哈哈,haha)
- 【springboot】【若依(ruoyi)】@RestController 接口支持 JSONP
- linux用户操作的日志,linux 用户操作记录并录入日志
- 【POJ - 2186】Popular Cows (Tarjan缩点)
- clickhouse-小结 mutation操作 视图
- 来自天国的 kubernetes
- 第二节 数值、字符与字符串
- 这么多技术我该怎么学 杨中科
- unity——小球酷跑游戏制作
- 移动端自动轮播可滑动轮播图
- 视频教程-C#入门经典视频精讲-C#
- mysql修复损坏表_在MySQL中,如何修复损坏的表
- Java面向对象程序设计(第二版)袁绍欣 第九章课后习题答案
- 回首十几年视频编解码之路
- vue echarts绘制省份地图并添加自定义标注
- 汇编电话本 15pb
- PMI-ACP练习题(19)