Netty+SpringBoot+FastDFS+Html5实现聊天App,项目介绍。
java
Netty+SpringBoot+FastDFS+Html5实现聊天App,项目github连接。
git
本章完整代码连接。
github
本章将给聊天App_PigChat加上心跳机制。segmentfault
若是没有特地的设置某些选项或者实现应用层心跳包,TCP空闲的时候是不会发送任何数据包。也就是说,当一个TCP的socket,客户端与服务端谁也不发送数据,会一直保持着链接。这其中若是有一方异常掉线(例如死机、路由被破坏、防火墙切断链接等),另外一端若是没有发送数据,永远也不可能知道。这对于一些服务型的程序来讲,是灾难性的后果,将会致使服务端socket资源耗尽。socket
举个简单的例子,当咱们由于特殊状况打开飞行模式 ,在处理完事件以后再关闭飞行模式,这时候若是再进入应用程序中,咱们将以新的channel进入,可是以前的channel仍是会保留。ide
所以,为了保证链接的有效性、及时有效地检测到一方的非正常断开,保证链接的资源被有效的利用,咱们就会须要一种保活的机制,一般改机制两种处理方式:netty
一、利用TCP协议层实现的Keepalive;code
二、本身在应用层实现心跳包。继承
新建一个HeartBeatHandler用于检测channel的心跳。事件
继承ChannelInboundHandlerAdapter,并重写其userEventTriggered方法。当客户端的全部ChannelHandler中4s内没有write事件,则会触发userEventTriggered方法。
首先咱们判断evt是不是IdleStateEvent的实例,IdleStateEvent用于触发用户事件,包含读空闲/写空闲/读写空闲。
对evt进行强制履行转换后,经过state判断其状态,只有当其该channel处于读写空闲的时候才将这个channel关闭。
/** * @Description: 用于检测channel的心跳handler * 继承ChannelInboundHandlerAdapter,从而不须要实现channelRead0方法 */ public class HeartBeatHandler extends ChannelInboundHandlerAdapter { @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { // 判断evt是不是IdleStateEvent(用于触发用户事件,包含 读空闲/写空闲/读写空闲 ) if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent)evt; // 强制类型转换 if (event.state() == IdleState.READER_IDLE) { System.out.println("进入读空闲..."); } else if (event.state() == IdleState.WRITER_IDLE) { System.out.println("进入写空闲..."); } else if (event.state() == IdleState.ALL_IDLE) { System.out.println("channel关闭前,users的数量为:" + ChatHandler.users.size()); Channel channel = ctx.channel(); // 关闭无用的channel,以防资源浪费 channel.close(); System.out.println("channel关闭后,users的数量为:" + ChatHandler.users.size()); } } } }
在原来的WSServerInitialzer中增长心跳机制的支持。
// ====================== 增长心跳支持 start ====================== // 针对客户端,若是在1分钟时没有向服务端发送读写心跳(ALL),则主动断开 // 若是是读空闲或者写空闲,不处理 pipeline.addLast(new IdleStateHandler(8, 10, 12)); // 自定义的空闲状态检测 pipeline.addLast(new HeartBeatHandler()); // ====================== 增长心跳支持 end ======================