2024年网络安全最全IdleStateHandler 心跳机制源码详解,2024年最新网络安全程序员必会

一、网安学习成长路线图

网安所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述

二、网安视频合集

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
在这里插入图片描述

三、精品网安学习书籍

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
在这里插入图片描述

四、网络安全源码合集+工具包

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
在这里插入图片描述

五、网络安全面试题

最后就是大家最关心的网络安全面试题板块
在这里插入图片描述在这里插入图片描述

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!




| 名称 | 作用 |
| --- | --- |
| `readerIdleTimeSeconds` | 读超时。即当在指定的时间间隔内没有从`Channel`读取到数据时,会触发一个`READER_IDLE`的`IdleStateEvent`事件 |
| `writerIdleTimeSeconds` | 写超时。即当在指定的时间间隔内没有数据写入到`Channel`时,会触发一个`WRITER_IDLE`的`IdleStateEvent`事件 |
| `allIdleTimeSeconds` | 读/写超时。即当在指定的时间间隔内没有读或写操作时,会触发一个`ALL_IDLE`的`IdleStateEvent`事件 |


### 三、IdleStateHandler 源码


【1】`handlerAdded`和`handlerRemoved`:`IdleStateHandler`是在创建`IdleStateHandler`实例并添加到`ChannelPipeline`时添加定时任务来进行定时检测的,具体在`initialize(ctx)`方法实现;同时在从`ChannelPipeline`移除或`Channel`关闭时,移除这个定时检测,具体在`destroy()`实现。`IdleStateHandler`的`channelActive()`方法在`socket`通道建立时被触发。




public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
if (ctx.channel().isActive() && ctx.channel().isRegistered()) {
this.initialize(ctx);
}

}

public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
this.destroy();
}

public void channelInactive(ChannelHandlerContext ctx) throws Exception {
this.destroy();
super.channelInactive(ctx);
}


【2】`initialize`:根据配置的`readerIdleTime`,`WriteIdleTIme`等超时事件参数往任务队列`taskQueue`中添加定时任务`task`。我先先查看`ReaderIdleTimeoutTask`的作用。




private void initialize(ChannelHandlerContext ctx) {
switch(this.state) {
case 1:
case 2:
return;
default:
this.state = 1;
this.initOutputChanged(ctx);
this.lastReadTime = this.lastWriteTime = this.ticksInNanos();
if (this.readerIdleTimeNanos > 0L) {
// 这里的 schedule 方法会调用 eventLoop 的 schedule 方法,将定时任务添加进队列中
this.readerIdleTimeout = this.schedule(ctx, new IdleStateHandler.ReaderIdleTimeoutTask(ctx), this.readerIdleTimeNanos, TimeUnit.NANOSECONDS);
}

    if (this.writerIdleTimeNanos > 0L) {
        this.writerIdleTimeout = this.schedule(ctx, new IdleStateHandler.WriterIdleTimeoutTask(ctx), this.writerIdleTimeNanos, TimeUnit.NANOSECONDS);
    }

    if (this.allIdleTimeNanos > 0L) {
        this.allIdleTimeout = this.schedule(ctx, new IdleStateHandler.AllIdleTimeoutTask(ctx), this.allIdleTimeNanos, TimeUnit.NANOSECONDS);
    }

}

}


定时任务添加到对应线程`EventLoopExecutor`对应的任务队列`taskQueue`中,在对应线程的`run()`方法中循环执行。只要给定的参数大于`0`,就创建一个定时任务,每个事件都创建。同时,将`state`状态设置为`1`,防止重复初始化。调用`initOutputChanged`方法,初始化**监控出站数据属性**




private void initOutputChanged(ChannelHandlerContext ctx) {
if (this.observeOutput) {
Channel channel = ctx.channel();
Unsafe unsafe = channel.unsafe();
ChannelOutboundBuffer buf = unsafe.outboundBuffer();
// 记录了出站缓冲区相关的数据,buf 对象的 hash 码,和 buf 的剩余缓冲字节数
if (buf != null) {
this.lastMessageHashCode = System.identityHashCode(buf.current());
this.lastPendingWriteBytes = buf.totalPendingWriteBytes();
this.lastFlushProgress = buf.currentProgress();
}
}
}


这边会触发一个`ReaderIdleTimeoutTask`:`nextDelay`的初始化值为超时秒数`readerIdleTimeNanos`。如果检测的时候没有正在读,且计算多久没读了,`nextDelay` -= 当前时间 - 上次读取时间,假如这个结果是`6s`,说明最后一次调用`channelRead`已经是`6s`之前的事情了,你设置的是`5s`,那么`nextDelay`则为`-1`,说明超时了。则创建`IdleStateEvent`事件,`IdleState`枚举值为`READER_IDLE`,然后调用`channelIdle`方法分发给下一个`ChannelInboundHandler`,通常由用户自定义一个`ChannelInboundHandler`来捕获并处理。




private final class ReaderIdleTimeoutTask extends IdleStateHandler.AbstractIdleTask {
ReaderIdleTimeoutTask(ChannelHandlerContext ctx) {
super(ctx);
}

protected void run(ChannelHandlerContext ctx) {
    long nextDelay = IdleStateHandler.this.readerIdleTimeNanos;
    if (!IdleStateHandler.this.reading) {
        nextDelay -= IdleStateHandler.this.ticksInNanos() - IdleStateHandler.this.lastReadTime;
    }

    if (nextDelay <= 0L) {
        IdleStateHandler.this.readerIdleTimeout = IdleStateHandler.this.schedule(ctx, this, IdleStateHandler.this.readerIdleTimeNanos, TimeUnit.NANOSECONDS);
        boolean first = IdleStateHandler.this.firstReaderIdleEvent;
        IdleStateHandler.this.firstReaderIdleEvent = false;

        try {
            IdleStateEvent event = IdleStateHandler.this.newIdleStateEvent(IdleState.READER\_IDLE, first);
            IdleStateHandler.this.channelIdle(ctx, event);
        } catch (Throwable var6) {
            ctx.fireExceptionCaught(var6);
        }
    } else {
        IdleStateHandler.this.readerIdleTimeout = IdleStateHandler.this.schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);
    }

}

}


`firstxxxxIdleEvent`作用:假设当你的客户端应用每次接收数据是`30`秒,而你的写空闲时间是`25`秒,那么,当你数据还没有写出的时候,写空闲时间触发了。实际上是不合乎逻辑的。因为你的应用根本不空闲。


`Netty`的解决方案是:记录最后一次输出消息的相关信息,并使用一个值`firstXXXXIdleEvent`表示是否再次活动过,每次读写活动都会将对应的`first`值更新为`true`,如果是`false`,说明这段时间没有发生过读写事件。同时如果第一次记录出站的相关数据和第二次得到的出站相关数据不同,则说明数据在缓慢的出站,就不用触发空闲事件。


总的来说,这个字段就是用来对付 “客户端接收数据奇慢无比,慢到比空闲时间还多” 的极端情况。所以,`Netty`默认是关闭这个字段的。


总的来说,每次读取操作都会记录一个时间,定时任务时间到了,会计算当前时间和最后一次读的时间的间隔,如果间隔超过了设置的时间,就触发·UserEventTriggered`方法:




protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {
ctx.fireUserEventTriggered(evt);
}


【3】写任务的`run`方法逻辑基本和读任务的逻辑一样,唯一不同的就是有一个针对 出站较慢数据的判断。




if (hasOutputChanged(ctx, first)) {
return;
}


如果这个方法返回`true`,就不执行触发事件操作了,即使时间到了。看看该方法实现:
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数网络安全工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**

![img](https://img-blog.csdnimg.cn/img_convert/bab8155354c4f0f60eddd8dbf4b2892b.png)

![img](https://img-blog.csdnimg.cn/img_convert/31de869c1c1fc40861bcf2bcbcc5e81c.png)

![img](https://img-blog.csdnimg.cn/img_convert/3fd2c6b8919ac09be2ddcd22bb6b6d08.png)

![img](https://img-blog.csdnimg.cn/img_convert/c7f0598dc8c7547b7393e6024945cabd.png)

![img](https://img-blog.csdnimg.cn/img_convert/62ac790299b11e19708171f213a2ca24.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618653875)

**由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

存中...(img-NCaq6Hyt-1715441084162)]

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上网络安全知识点!真正的体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618653875)

**由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!**

  • 28
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值