主要逻辑

使用netty实现长连接,主要靠心跳来维持服务器端及客户端连接。

实现的逻辑主要是:

服务器端方面

1, 服务器在网络空闲操作一定时间后,服务端失败心跳计数器加1。

2, 如果收到客户端的ping心跳包,则清零失败心跳计数器,如果连续n次未收到客户端的ping心跳包,则关闭链路,释放资源,等待客户端重连。

客户端方面

1, 客户端网络空闲在一定时间内没有进行写操作时,则发送一个ping心跳包。

2, 如果服务器端未在发送下一个心跳包之前回复pong心跳应答包,则失败心跳计数器加1。

3, 如果客户端连续发送n(此处根据具体业务进行定义)次ping心跳包,服务器端均未回复pong心跳应答包,则客户端断开连接,间隔一定时间进行重连操作,直至连接服务器成功。

环境:netty5,tomcat7,jdk7,myeclipse

服务器端心跳处理类:

  1. public class HeartBeatRespHandler extends ChannelInboundHandlerAdapter {
  2. private  final Logger log=Logger.getLogger(HeartBeatRespHandler.class);
  3. //线程安全心跳失败计数器
  4. private AtomicInteger unRecPingTimes = new AtomicInteger(1);
  5. @Override
  6. public void channelRead(ChannelHandlerContext ctx, Object msg)
  7. throws Exception {
  8. NettyMessageProto message = (NettyMessageProto)msg;
  9. unRecPingTimes = new AtomicInteger(1);
  10. //接收客户端心跳信息
  11. if(message.getHeader() != null  && message.getHeader().getType() == Constants.MSGTYPE_HEARTBEAT_REQUEST){
  12. //清零心跳失败计数器
  13. log.info("server receive client"+ctx.channel().attr(SysConst.SERIALNO_KEY)+" ping msg :---->"+message);
  14. //接收客户端心跳后,进行心跳响应
  15. NettyMessageProto replyMsg = buildHeartBeat();
  16. ctx.writeAndFlush(replyMsg);
  17. }else{
  18. ctx.fireChannelRead(msg);
  19. }
  20. }
  21. /**
  22. * 事件触发器,该处用来处理客户端空闲超时,发送心跳维持连接。
  23. */
  24. @Override
  25. public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
  26. if (evt instanceof IdleStateEvent) {
  27. IdleStateEvent event = (IdleStateEvent) evt;
  28. if (event.state() == IdleState.READER_IDLE) {
  29. /*读超时*/
  30. log.info("===服务器端===(READER_IDLE 读超时)");
  31. unRecPingTimes.getAndIncrement();
  32. //客户端未进行ping心跳发送的次数等于3,断开此连接
  33. if(unRecPingTimes.intValue() == 3){
  34. ctx.disconnect();
  35. System.out.println("此客户端连接超时,服务器主动关闭此连接....");
  36. log.info("此客户端连接超时,服务器主动关闭此连接....");
  37. }
  38. } else if (event.state() == IdleState.WRITER_IDLE) {
  39. /*服务端写超时*/
  40. log.info("===服务器端===(WRITER_IDLE 写超时)");
  41. } else if (event.state() == IdleState.ALL_IDLE) {
  42. /*总超时*/
  43. log.info("===服务器端===(ALL_IDLE 总超时)");
  44. }
  45. }
  46. }
  47. /**
  48. * 创建心跳响应消息
  49. * @return
  50. */
  51. private NettyMessageProto buildHeartBeat(){
  52. HeaderProto header = HeaderProto.newBuilder().setType(Constants.MSGTYPE_HEARTBEAT_RESPONSE).build();
  53. NettyMessageProto message =NettyMessageProto.newBuilder().setHeader(header).build();
  54. return message;
  55. }

客户端心跳处理类:

  1. public class HeartBeatReqHandler extends ChannelHandlerAdapter {
  2. private  final Logger log=Logger.getLogger(HeartBeatReqHandler.class);
  3. //线程安全心跳失败计数器
  4. private AtomicInteger unRecPongTimes = new AtomicInteger(1);
  5. public void channelRead(ChannelHandlerContext ctx, Object msg)
  6. throws Exception {
  7. NettyMessageProto message = (NettyMessageProto)msg;
  8. //服务器端心跳回复
  9. if(message.getHeader() != null  && message.getHeader().getType() == Constants.MSGTYPE_HEARTBEAT_RESPONSE){
  10. //如果服务器进行pong心跳回复,则清零失败心跳计数器
  11. unRecPongTimes = new AtomicInteger(1);
  12. log.debug("client receive server pong msg :---->"+message);
  13. }else{
  14. ctx.fireChannelRead(msg);
  15. }
  16. }
  17. /**
  18. * 事件触发器,该处用来处理客户端空闲超时,发送心跳维持连接。
  19. */
  20. public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
  21. if (evt instanceof IdleStateEvent) {
  22. IdleStateEvent event = (IdleStateEvent) evt;
  23. if (event.state() == IdleState.READER_IDLE) {
  24. /*读超时*/
  25. log.info("===客户端===(READER_IDLE 读超时)");
  26. } else if (event.state() == IdleState.WRITER_IDLE) {
  27. /*客户端写超时*/
  28. log.info("===客户端===(WRITER_IDLE 写超时)");
  29. unRecPongTimes.getAndIncrement();
  30. //服务端未进行pong心跳响应的次数小于3,则进行发送心跳,否则则断开连接。
  31. if(unRecPongTimes.intValue() < 3){
  32. //发送心跳,维持连接
  33. ctx.channel().writeAndFlush(buildHeartBeat()) ;
  34. log.info("客户端:发送心跳");
  35. }else{
  36. ctx.channel().close();
  37. }
  38. } else if (event.state() == IdleState.ALL_IDLE) {
  39. /*总超时*/
  40. log.info("===客户端===(ALL_IDLE 总超时)");
  41. }
  42. }
  43. }
  44. private NettyMessageProto buildHeartBeat(){
  45. HeaderProto header = HeaderProto.newBuilder().setType(Constants.MSGTYPE_HEARTBEAT_REQUEST).build();
  46. NettyMessageProto  message = NettyMessageProto.newBuilder().setHeader(header).build();
  47. return message;
  48. }
  49. /**
  50. * 异常处理
  51. */
  52. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)throws Exception{
  53. ctx.fireExceptionCaught(cause);
  54. }
  55. }
  1. <pre code_snippet_id="2489110" snippet_file_name="blog_20170719_2_6056366" name="code" class="java"><pre code_snippet_id="2489110" snippet_file_name="blog_20170719_2_6056366"></pre><pre></pre><pre></pre><pre></pre><pre></pre><pre></pre><pre></pre><pre></pre><pre></pre><pre></pre><pre></pre><pre></pre><pre></pre><pre></pre></pre>
  2. <pre></pre>
  3. <pre></pre>
  4. <pre></pre>
  5. <pre></pre>
  6. <link rel="stylesheet" href="http://static.blog.csdn.net/public/res-min/markdown_views.css?v=1.0">
 
 

版权声明:本文为博主原创文章,未经博主允许不得转载。

netty实现长连接心跳检的更多相关文章

  1. 转 互联网推送服务原理:长连接+心跳机制(MQTT协议)

    http://blog.csdn.net/zhangzeyuaaa/article/details/39028369 目录(?)[-] 无线移动网络的特点 android系统的推送和IOS的推送有什么 ...

  2. 互联网推送服务原理:长连接+心跳机制(MQTT协议)

    互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...

  3. 移动互联网消息推送原理:长连接+心跳机制(MQTT协议)

    互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...

  4. [转]Android TCP长连接 心跳机制及实现

    背景知识 智能手机上的长连接心跳和在Internet上的长连接心跳有什么不同 Android系统的推送和iOS的推送有什么区别 几种推送的实现方式 协议 1XMPP简介 2 MQTT简介 3移动端消息 ...

  5. Netty(一) SpringBoot 整合长连接心跳机制

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

  6. Python WebSocket长连接心跳与短连接

    python websocket 安装 pip install websocket-client 先来看一下,长连接调用方式: ws = websocket.WebSocketApp("ws ...

  7. Android实现推送方式解决方案 - 长连接+心跳机制(MQTT协议)

    本文介绍在Android中实现推送方式的基础知识及相关解决方案.推送功能在手机开发中应用的场景是越来起来了,不说别的,就我们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅读最新的新闻信息. ...

  8. TCP keepalive长连接心跳保活

    比如:客户端与服务端进行握手时,经常无法握手成功,收不到回复: 需要建立保活机制. 1. 服务端Linux服务器新增系统内核参数配置. 在/etc/sysctl.conf文件中再添加如: #允许的持续 ...

  9. java Socket 长连接 心跳包 客户端 信息收发 demo

    今天写了个socket的测试小程序,代码如下 import java.io.IOException; import java.io.InputStream; import java.io.Output ...

随机推荐

  1. PAT——乙级1001and1011

    准备明年年初考PAT,练题呀,暂且先把LeetCode放下. 我是按照算法笔记这个教材刷的. B1001 1001 害死人不偿命的(3n+1)猜想 (15 point(s)) 卡拉兹(Callatz) ...

  2. MFC之HTTP文件上传

    BOOL UploadFile(LPCTSTR strURL, LPCTSTR strLocalFileName) { // 如果URL为空或者文件不存在,直接返回 if (strURL == NUL ...

  3. 【bzoj3217】ALOEXT 替罪羊树套Trie树

    题目描述 taorunz平时最喜欢的东西就是可移动存储器了……只要看到别人的可移动存储器,他总是用尽一切办法把它里面的东西弄到手. 突然有一天,taorunz来到了一个密室,里面放着一排可移动存储器, ...

  4. [LOJ#2330]「清华集训 2017」榕树之心

    [LOJ#2330]「清华集训 2017」榕树之心 试题描述 深秋.冷风吹散了最后一丝夏日的暑气,也吹落了榕树脚下灌木丛的叶子.相识数年的Evan和Lyra再次回到了小时候见面的茂盛榕树之下.小溪依旧 ...

  5. bzoj 3704 昊昊的机油之GRST 贪心dp,思维

    昊昊的机油之GRST Time Limit: 10 Sec  Memory Limit: 1024 MBSubmit: 80  Solved: 33[Submit][Status][Discuss] ...

  6. 使用 swagger组件给asp.net webapi文档生成

    1.名词解释 Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法,参数和模 ...

  7. 美食节(bzoj 2879)

    Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽 ...

  8. linux把时间类型值转换为数值型

    字符及字符串处理函数:字符及字符串处理函数的处理对象均为字符型数据,但其返回值类型各异.1.取子串函数:格式:substr(c,n1,n2)功能:取字符串C第n1个字符起的n2个字符.返回值类型是字符 ...

  9. 【HDOJ5510】Bazinga(KMP)

    题意:给定n个由小写字母组成的字符串,第i个字符串为a[i],求最大的j满足存在1<=i<j,a[i]不是a[j]的子串,无解输出-1 T<=50,n<=500,len[i]& ...

  10. HTTP 错误 401.2 - Unauthorized

    最近开始拾起Asp.net方面的知识,遇到如下这个问题 HTTP 错误 401.2 - Unauthorized 由于身份验证头无效,您无权查看此页. 解决方法: >IIS管理 >功能视图 ...