小尾巴鱼 发表于 2015-07-02 11:12

嵌入式工程师互助:34分钟12问14答解决“服务器端定时检测在线的客户端—心跳处理”

背景:如果您有棘手的技术问题,您会选择什么方式解决?百度一下搜索网络答案?还是找一位高手求问!高手可遇不可求,实际问题场景中,也是仁者见仁或猴子快上树或鸟儿空中飞,互联网飞速发展,IT168企业级一直陪伴着大家,从论坛、全国技术沙龙到技术峰会(DTCC\SACC\高峰精英论坛),我们一直在努力平衡“广大技术从业者技术提升”与“IT厂商新产品及服务的普及。我们一直在路上,或行走或奔跑,我们路行之风,是否能凉爽到路过的你?
关于技术问与答,建议加入IT欢乐群及各分类技术群!261358889群号关于技术快速集训营:建议参与我们的数据库大会、架构师大会、IT精英论坛!
最新消息:架构师大会将于2015年10月22日盛大开幕!购票入口:http://sacc.it168.com/
赠票活动:技术自白书征文活动 http://bbs.chinaunix.net/thread-4181131-1-1.html


以下内容产生于6月25日22:47-23:11   IT欢乐群之分类技术QQ群!在此感谢,回答与提问者的精进,技术生活虽平淡,却因有你们的无私与勤恳而更精彩!
问:若客服端在一定时间内没向服务器端发送消息,就将此客服端从服务器例表删除,就是心跳包要怎么处理?

答:比如你可以客户端每隔20秒向服务器端发送一个http格式的心跳包

问:我是从键盘获取。用fgets()

答:思路明确没?现在卡在哪?

问:我该如何判断fgets(buff, N, stdin);在一点时间内是没有输入的?只要判断它在一点时间内没有输入就让服务器对其做下线处理

答:(1)能不能加信号,键盘输入应该会出发信号。
      (2)可以写个倒计时啥的时间结束还没收到就让其下线。

问:我想到过用select,但是服务器端要接收多个客户端的消息并处理啊,我服务器端使用链表实现客户端用户存储的,所以I/O多用复用又不好整了。

答:你应该换个思路。

问:您说该怎么换思路,求指教

答:最好定期发给服务端发一个消息,就是心跳,服务端收不到就删除对应的用户节点。


问:嗯 ,那这个心跳包和键盘的输入怎么平衡呢?

答:(1)不影响的,在心跳之内还没发就下线啊
      (2)心跳要有固定格式,发过去服务器端解析出,只要格式正确就保持在线。

问:定义一个结构体?

答:(1)对自己约定一个格式就好=哪怕是一个字符
      (2)不是就是一个字符串就行,加关键字。这样做还有一个好处,比如客户端完成任务后可以向服务器端发请求下线,服务器端只要做消息处理就行。

问:那请问在服务器端该怎么在链表里去处理呢?就像我有写客户端发送quit,客户端就下线 ,服务器端就删除该用户


答:你一个连标节点就是一个用户对吧。


问:是

答:那个节点发的消息就处理哪个节点。
问:每个节点 一个用户?

答:嗯,对,就那样。理解了吗?


问:再请教一个较基础的问题,请问在客户端那个定时该怎么做,用sleep睡眠?


答:就是一个while循环,每隔多少秒不停发心跳。最好用一个计算时间查的小算法。还有为了保证数据的安全或准确行最好发送消息时用协议包装 这个你先慢慢来。

ilydba 发表于 2015-07-02 11:34

占楼:lol:lol:lol:lol:lol

sheepbao 发表于 2015-07-02 17:37

:emn23:来顶

seesea2517 发表于 2015-07-06 13:06

标题的“客服端”应该改“客户端” :D

小尾巴鱼 发表于 2015-07-06 14:28

好滴

myworkstation 发表于 2015-07-06 18:44

不错不错,可以定期更新top questions,

yulihua49 发表于 2015-07-11 16:48

本帖最后由 yulihua49 于 2015-07-11 19:18 编辑

小尾巴鱼 发表于 2015-07-02 11:12 static/image/common/back.gif
背景:如果您有棘手的技术问题,您会选择什么方式解决?百度一下搜索网络答案?还是找一位高手求问!高手可 ...答:就是一个while循环,每隔多少秒不停发心跳。最好用一个计算时间查的小算法。还有为了保证数据的安全或准确行最好发送消息时用协议包装 这个你先慢慢来。

没这么简单。
你必须保证心跳不干扰正常通信。做业务时心跳必须停。
心跳等待应答期间业务要等待心跳完成。
我更倾向不用心跳。不用时关闭连接,使用时打开。这个工作可以交给连接池处理。
应用对连接池的调用就是取用和归还。取用时发现连接失效可以重连。连接池发现连接长时间不用可以自动关闭。
如果应用使用频繁,那它本身就是心跳。如果使用不频繁,那就没必要老开着连接。

yulihua49 发表于 2015-07-11 19:23

本帖最后由 yulihua49 于 2015-07-11 19:25 编辑

小尾巴鱼 发表于 2015-07-02 11:12 static/image/common/back.gif
背景:如果您有棘手的技术问题,您会选择什么方式解决?百度一下搜索网络答案?还是找一位高手求问!高手可 ...问:若客服端在一定时间内没向服务器端发送消息,就将此客服端从服务器例表删除,就是心跳包要怎么处理?

答:比如你可以客户端每隔20秒向服务器端发送一个http格式的心跳包

答非所问。人家问客户的没发信息怎么处理。
正确答案是利用超时机制发现客户端超时。
一般可以用TCP超时,setsocketopt。 有的系统不支持。epoll和select也不支持,就需要自己设置超时监控子系统,通常单独用个线程。
它监控每一个连接的状态,发现哪个超时就发通知把它从等待队列清除,并进行善后工作。

qianhng 发表于 2015-07-20 16:07

yulihua49 发表于 2015-07-11 16:48 static/image/common/back.gif
没这么简单。
。。。。。。
取用时发现连接失效可以重连
。。。。。。
..
连接失效是个什么状态?
如何重连对方,对方又没有listen?

yulihua49 发表于 2015-07-23 15:23

本帖最后由 yulihua49 于 2015-07-31 19:40 编辑

要看连接池的状态。如果初始状态(一切连接均无效),就产生新连接。这自然知道是否成功。长时间不用的连接被强制恢复成初始态。结果同上。使用中的连接,发现故障(发送或接收错误),需要自行夭折你的后续操作。当前的故障连接要归还并关闭。这个连接自然恢复到初始态。一般的连接故障不可能很快恢复,所以没必要自动重连。业务的rollback,redo,abort等操作你自己设计
连接池是个客户端的装置。服务器不是这样的,它只需要超时关闭客户端连接即可,我们一般设置服务器超时6分钟,客户端(连接池)超时5分钟。这样总是保证客户端抢先关闭。应用不会出任何问题。如果客户端一直繁忙,服务器也不会探测到超时。双方的超时都是在发生真正的网络故障。
把我的回帖完整看一遍就可以理解了。
页: [1]
查看完整版本: 嵌入式工程师互助:34分钟12问14答解决“服务器端定时检测在线的客户端—心跳处理”