netty心跳过程中 发送消息失败_netty心跳机制和断线重连(四)

心跳是为了保证客户端和服务端的通信可用。因为各种原因客户端和服务端不能及时响应和接收信息。比如网络断开,停电 或者是客户端/服务端 高负载。

所以每隔一段时间 客户端发送心跳包到客户端  服务端做出心跳的响应;

1.如果客户端在指定时间没有向服务端发送心跳包。则表示客户端的通信出现了问题。

2.如果客户端发送心跳包到服务端没有收到响应 则表示服务端的通信出现了问题。

netty提供IdleStateHandle 在监听距离上一次写的时间和距离上一次读的时间 如果超时则调用

源码:

public class IdleStateHandler extendsChannelDuplexHandler

@Overridepublic void channelActive(ChannelHandlerContext ctx) throwsException {//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);

}

}

private voidinitialize(ChannelHandlerContext ctx) {//Avoid the case where destroy() is called before scheduling timeouts.//See:https://github.com/netty/netty/issues/143

switch(state) {case 1:case 2:return;

}

state= 1;

initOutputChanged(ctx);

lastReadTime= lastWriteTime =ticksInNanos();if (readerIdleTimeNanos > 0) {

readerIdleTimeout= schedule(ctx, newReaderIdleTimeoutTask(ctx),//监听read的task

readerIdleTimeNanos, TimeUnit.NANOSECONDS);

}if (writerIdleTimeNanos > 0) {

writerIdleTimeout= schedule(ctx, newWriterIdleTimeoutTask(ctx),//监听写的task

writerIdleTimeNanos, TimeUnit.NANOSECONDS);

}if (allIdleTimeNanos > 0) {

allIdleTimeout= schedule(ctx, newAllIdleTimeoutTask(ctx),//监听读写的task

allIdleTimeNanos, TimeUnit.NANOSECONDS);

}

}

private final class ReaderIdleTimeoutTask extendsAbstractIdleTask {

ReaderIdleTimeoutTask(ChannelHandlerContext ctx) {super(ctx);

}

@Overrideprotected voidrun(ChannelHandlerContext ctx) {long nextDelay =readerIdleTimeNanos;if (!reading) {

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);

}catch(Throwable t) {

ctx.fireExceptionCaught(t);

}

}else{//Read occurred before the timeout - set a new timeout with shorter delay.

readerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);

}

}

}private final class WriterIdleTimeoutTask extendsAbstractIdleTask {

WriterIdleTimeoutTask(ChannelHandlerContext ctx) {super(ctx);

}

@Overrideprotected voidrun(ChannelHandlerContext ctx) {long lastWriteTime = IdleStateHandler.this.lastWriteTime;long nextDelay = writerIdleTimeNanos - (ticksInNanos() -lastWriteTime);if (nextDelay <= 0) {//Writer is idle - set a new timeout and notify the callback.

writerIdleTimeout = schedule(ctx, this, writerIdleTimeNanos, TimeUnit.NANOSECONDS);boolean first =firstWriterIdleEvent;

firstWriterIdleEvent= false;try{if(hasOutputChanged(ctx, first)) {return;

}

IdleStateEvent event=newIdleStateEvent(IdleState.WRITER_IDLE, first);

channelIdle(ctx, event);

}catch(Throwable t) {

ctx.fireExceptionCaught(t);

}

}else{//Write occurred before the timeout - set a new timeout with shorter delay.

writerIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);

}

}

}private final class AllIdleTimeoutTask extendsAbstractIdleTask {

AllIdleTimeoutTask(ChannelHandlerContext ctx) {super(ctx);

}

@Overrideprotected voidrun(ChannelHandlerContext ctx) {long nextDelay =allIdleTimeNanos;if (!reading) {

nextDelay-= ticksInNanos() -Math.max(lastReadTime, lastWriteTime);

}if (nextDelay <= 0) {//Both reader and writer are idle - set a new timeout and//notify the callback.

allIdleTimeout = schedule(ctx, this, allIdleTimeNanos, TimeUnit.NANOSECONDS);boolean first =firstAllIdleEvent;

firstAllIdleEvent= false;try{if(hasOutputChanged(ctx, first)) {return;

}

IdleStateEvent event=newIdleStateEvent(IdleState.ALL_IDLE, first);

channelIdle(ctx, event);

}catch(Throwable t) {

ctx.fireExceptionCaught(t);

}

}else{//Either read or write occurred before the timeout - set a new//timeout with shorter delay.

allIdleTimeout = schedule(ctx, this, nextDelay, TimeUnit.NANOSECONDS);

}

}

}

三个内部类是IdleSateHandle的内部类 可以看到内部是通过另起一个线程进行监听上一次对应事件的触发 如果超时则调用对应的事件

基于三的代码进行修改

首先是MessageHead消息头增加消息类型

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值