linux多线程 心跳机制怎么实现呢?

xdh0817 2013-08-26 08:31:37

TCP服务,长连接。
首先一个s(服务器)和一个c(客户端)建立TCP连接,S向C发送数据。C有两个线程:一个收数据;一个将数据保存到本地,保存成功以后向S回复一个确认。
因为是长连接,所以要加一个心跳检测,C每隔100秒向S发一个心跳数据包,S收到包以后会给C一个回复。如果C没有在10秒内收到回复,则再次向S发心跳包,如果仍然没有在10秒内收到回复,则认为连接已经断了,则需要重新connect服务器。
基本功能实现了,现在缺少心跳检测功能。心跳怎么实现呢?听起来简单,实现起来发现不容易,各位大牛指点一下啊

...全文
1201 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
xdh0817 2013-08-29
  • 打赏
  • 举报
回复
引用 18 楼 listenerxu 的回复:
[quote=引用 16 楼 xdh0817 的回复:] [quote=引用 13 楼 listenerxu 的回复:] 单独开线程干嘛?自己封装一个定时器,在C的那个保存数据的线程的循环中去检测是否有定时器被触发了,定时器触发就去干自己的逻辑吧。 不过有点不理解,你是服务器要去发送心跳包是不是更好了?在第二次触发定时器的时候主动关闭连接
说的轻松啊!仔细想过么?[/quote] 不是没想过,而是已经做过[/quote] 怎么封装定时器?
xdh0817 2013-08-29
  • 打赏
  • 举报
回复
引用 21 楼 lufeipeng 的回复:
逻辑层的心跳包还是有必要的,严格的tcp socket网络程序,一般采用双向心跳,服务器和客户端都需要一套心跳机制, 底层keepalive超时的时间比较长,不一定适用 参考: http://blog.csdn.net/lufeipeng/article/details/7227901 心跳包的检测可以放在客户端接收线程中 例如: unsigned int timetick_sec; //保存发送心跳包的时间 const static int timeout_interval = 10; //心跳包间隔时间 //接收到心跳包,记录下接收到的时间 void recvtimetick() { timetick_sec = time(NULL); } //发送心跳包,记录下发送的时间 void sendtimetick() { timetick_sec = time(NULL); } void checktimeout() { //放入到接收线程的主循环中, 当前的时间 - 接收服务器消息的时间 > 2 * timeout_interval, 断开socket连接 if(time(NULL) - timetick_sec > 2 * timeout_interval) { close(socket); } }
现在基本上是这个思路~
xdh0817 2013-08-28
  • 打赏
  • 举报
回复
引用 14 楼 a107316170 的回复:
首先我觉得你这样做就有问题,tcp自己就有一套心跳机制(tcp的KEEPALIVE选项), 详细说明请看:http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html
keepalive不好,自己写心跳包好一些吧
卢飞鹏 2013-08-28
  • 打赏
  • 举报
回复
逻辑层的心跳包还是有必要的,严格的tcp socket网络程序,一般采用双向心跳,服务器和客户端都需要一套心跳机制, 底层keepalive超时的时间比较长,不一定适用 参考: http://blog.csdn.net/lufeipeng/article/details/7227901 心跳包的检测可以放在客户端接收线程中 例如: unsigned int timetick_sec; //保存发送心跳包的时间 const static int timeout_interval = 10; //心跳包间隔时间 //接收到心跳包,记录下接收到的时间 void recvtimetick() { timetick_sec = time(NULL); } //发送心跳包,记录下发送的时间 void sendtimetick() { timetick_sec = time(NULL); } void checktimeout() { //放入到接收线程的主循环中, 当前的时间 - 接收服务器消息的时间 > 2 * timeout_interval, 断开socket连接 if(time(NULL) - timetick_sec > 2 * timeout_interval) { close(socket); } }
上三行 2013-08-28
  • 打赏
  • 举报
回复
首先我觉得你这样做就有问题,tcp自己就有一套心跳机制(tcp的KEEPALIVE选项), 详细说明请看:http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html
上三行 2013-08-28
  • 打赏
  • 举报
回复
引用 15 楼 xdh0817 的回复:
[quote=引用 14 楼 a107316170 的回复:] 首先我觉得你这样做就有问题,tcp自己就有一套心跳机制(tcp的KEEPALIVE选项), 详细说明请看:http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html
keepalive不好,自己写心跳包好一些吧[/quote] 不好,那为什么要添加到linux内核中去呢?linux内核代码的审核是很严格的
追_逐 2013-08-28
  • 打赏
  • 举报
回复
什么是长连接,什么是心跳检测? 做的什么项目里面要用到这两个东西呢?
monster_xu 2013-08-28
  • 打赏
  • 举报
回复
引用 16 楼 xdh0817 的回复:
[quote=引用 13 楼 listenerxu 的回复:] 单独开线程干嘛?自己封装一个定时器,在C的那个保存数据的线程的循环中去检测是否有定时器被触发了,定时器触发就去干自己的逻辑吧。 不过有点不理解,你是服务器要去发送心跳包是不是更好了?在第二次触发定时器的时候主动关闭连接
说的轻松啊!仔细想过么?[/quote] 不是没想过,而是已经做过
xdh0817 2013-08-28
  • 打赏
  • 举报
回复
现在基本实现了心跳功能了。用逻辑判断 + sleep做的
xdh0817 2013-08-28
  • 打赏
  • 举报
回复
引用 13 楼 listenerxu 的回复:
单独开线程干嘛?自己封装一个定时器,在C的那个保存数据的线程的循环中去检测是否有定时器被触发了,定时器触发就去干自己的逻辑吧。 不过有点不理解,你是服务器要去发送心跳包是不是更好了?在第二次触发定时器的时候主动关闭连接
说的轻松啊!仔细想过么?
xdh0817 2013-08-27
  • 打赏
  • 举报
回复
引用 8 楼 qiyu1988 的回复:
想法没错,问题是你所用的类似kernel里面的del_timer之类的函数,linux应用层没有。 我上面说的是应用层可用timer的一种方式
#include<linux/timer.h>这样不行吗? 另外你的思路是: 心跳线程: while(1) { if (flag == 0) { break; //跳出while,重新连接 } sleep(100 - i * 1); time_now = now(); global = time_now + 20; //将全局变量设的比较大。 for (i = 0; i < 10; i++) { sleep(1); if (global - time_now < 10) { flag = 1; //表示收到了回复 break; } } if (i == 10) flag = 0; //表示没收到回复 } connect(); 接收线程: for( ; ; ) { read(sock, buf[], n); switch (buf[0]) case data: xxx;break; case 心跳回复: global = now();break; } 你是这个意思吧??
qiyu1988 2013-08-27
  • 打赏
  • 举报
回复
想法没错,问题是你所用的类似kernel里面的del_timer之类的函数,linux应用层没有。 我上面说的是应用层可用timer的一种方式
xdh0817 2013-08-27
  • 打赏
  • 举报
回复 1
引用 6 楼 qiyu1988 的回复:
[quote=引用 5 楼 xdh0817 的回复:] [quote=引用 4 楼 qiyu1988 的回复:] 在通信的循环里使用gettimeofday之类的函数获取时间 发送的时候记录一次时间,每次或每N次进循环体再获取时间,判断10s是不是过去了,如果过去了就判断有没收到确认包
这样肯定不行啊!我的目的是收数据啊! 接收数据线程实时收数据;保存数据线程实时保存;心跳线程发心跳。 我现在的想法是:心跳线程发心跳时启动一个定时10秒的定时器。接收数据线程收到心跳回复就删除定时器。 其中定时器的超时处理函数功能就是:一切归零,重新连接!(极端一点)[/quote] 其实你缺少的只是一个计时的方式而已,在心跳线程里面使用系统函数计时也是一样的啊。linux所使用的定时器大体都是gettimeofday这类函数实现的,而且在你的程序里,定时器只是工具,不是目的。你在不同的时间段获取系统时间,加减一下就可以判断多少时间过去了,进而实现相应的功能[/quote] 按我的想法 心跳线程: while(1) { sleep(100);// if (0 == flag) { break; } init_timer(&xxx); xxx.function = fun();//func为超时函数,比如超时就置标志位为0: flag = 0; add_timer } connect();//跳出while重新连接。 接收线程: for( ; ; ) { read(sock, buf[], n); switch (buf[0]) case data: xxx;break; case 心跳回复: del_timer(&xxx);break; } 按你的说法是怎样的呢?
xdh0817 2013-08-27
  • 打赏
  • 举报
回复
别沉啊,大家一起讨论讨论。难道是我的这个问题简单的让人懒得回答?
qiyu1988 2013-08-27
  • 打赏
  • 举报
回复
引用 9 楼 xdh0817 的回复:
[quote=引用 8 楼 qiyu1988 的回复:] 想法没错,问题是你所用的类似kernel里面的del_timer之类的函数,linux应用层没有。 我上面说的是应用层可用timer的一种方式
#include<linux/timer.h>这样不行吗? 另外你的思路是: 心跳线程: while(1) { if (flag == 0) { break; //跳出while,重新连接 } sleep(100 - i * 1); time_now = now(); global = time_now + 20; //将全局变量设的比较大。 for (i = 0; i < 10; i++) { sleep(1); if (global - time_now < 10) { flag = 1; //表示收到了回复 break; } } if (i == 10) flag = 0; //表示没收到回复 } connect(); 接收线程: for( ; ; ) { read(sock, buf[], n); switch (buf[0]) case data: xxx;break; case 心跳回复: global = now();break; } 你是这个意思吧?? [/quote] 嗯
monster_xu 2013-08-27
  • 打赏
  • 举报
回复
单独开线程干嘛?自己封装一个定时器,在C的那个保存数据的线程的循环中去检测是否有定时器被触发了,定时器触发就去干自己的逻辑吧。 不过有点不理解,你是服务器要去发送心跳包是不是更好了?在第二次触发定时器的时候主动关闭连接
xdh0817 2013-08-27
  • 打赏
  • 举报
回复
引用 10 楼 qiyu1988 的回复:
[quote=引用 9 楼 xdh0817 的回复:] [quote=引用 8 楼 qiyu1988 的回复:] 想法没错,问题是你所用的类似kernel里面的del_timer之类的函数,linux应用层没有。 我上面说的是应用层可用timer的一种方式
#include<linux/timer.h>这样不行吗? 另外你的思路是: 心跳线程: while(1) { if (flag == 0) { break; //跳出while,重新连接 } sleep(100 - i * 1); time_now = now(); global = time_now + 20; //将全局变量设的比较大。 for (i = 0; i < 10; i++) { sleep(1); if (global - time_now < 10) { flag = 1; //表示收到了回复 break; } } if (i == 10) flag = 0; //表示没收到回复 } connect(); 接收线程: for( ; ; ) { read(sock, buf[], n); switch (buf[0]) case data: xxx;break; case 心跳回复: global = now();break; } 你是这个意思吧?? [/quote] 嗯[/quote] #include<linux/timer.h> 果然不行,no such file or directroy 我觉得用定时器挺好的啊,比如写一个定时模块,创建一个定时器就加入到链表,并得到ID。 可是no such file or directroy这个怎么解决呢?我已经包含头文件了啊
qiyu1988 2013-08-26
  • 打赏
  • 举报
回复
引用 5 楼 xdh0817 的回复:
[quote=引用 4 楼 qiyu1988 的回复:] 在通信的循环里使用gettimeofday之类的函数获取时间 发送的时候记录一次时间,每次或每N次进循环体再获取时间,判断10s是不是过去了,如果过去了就判断有没收到确认包
这样肯定不行啊!我的目的是收数据啊! 接收数据线程实时收数据;保存数据线程实时保存;心跳线程发心跳。 我现在的想法是:心跳线程发心跳时启动一个定时10秒的定时器。接收数据线程收到心跳回复就删除定时器。 其中定时器的超时处理函数功能就是:一切归零,重新连接!(极端一点)[/quote] 其实你缺少的只是一个计时的方式而已,在心跳线程里面使用系统函数计时也是一样的啊。linux所使用的定时器大体都是gettimeofday这类函数实现的,而且在你的程序里,定时器只是工具,不是目的。你在不同的时间段获取系统时间,加减一下就可以判断多少时间过去了,进而实现相应的功能
xdh0817 2013-08-26
  • 打赏
  • 举报
回复
引用 4 楼 qiyu1988 的回复:
在通信的循环里使用gettimeofday之类的函数获取时间 发送的时候记录一次时间,每次或每N次进循环体再获取时间,判断10s是不是过去了,如果过去了就判断有没收到确认包
这样肯定不行啊!我的目的是收数据啊! 接收数据线程实时收数据;保存数据线程实时保存;心跳线程发心跳。 我现在的想法是:心跳线程发心跳时启动一个定时10秒的定时器。接收数据线程收到心跳回复就删除定时器。 其中定时器的超时处理函数功能就是:一切归零,重新连接!(极端一点)
qiyu1988 2013-08-26
  • 打赏
  • 举报
回复
在通信的循环里使用gettimeofday之类的函数获取时间 发送的时候记录一次时间,每次或每N次进循环体再获取时间,判断10s是不是过去了,如果过去了就判断有没收到确认包
加载更多回复(3)

23,124

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧