12 | 连接无效:使用Keep-Alive还是应用心跳来检测?
该思维导图由 AI 生成,仅供参考
从一个例子开始
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了在网络编程中如何检测连接状态的最佳实践。作者首先通过一个基于NATS消息系统的故障案例引出了连接状态检测的重要性。接着详细介绍了TCP的Keep-Alive机制,包括其原理和在Linux系统中的相关设置。作者指出了TCP保活机制的局限性,提出了在应用层实现连接探活的解决方案。最后,作者介绍了在应用层设计PING-PONG协议的关键点,并给出了消息格式设计的示例。通过本文,读者可以了解到TCP保活机制的原理和局限性,以及在应用层实现连接探活的方法,为网络编程中连接状态的检测提供了有益的参考。 文章通过客户端和服务器端程序设计,演示了如何利用select函数和心跳包实现TCP连接的保活机制。通过实验,展示了不同休眠时间对连接状态的影响,以及如何通过多次探活来判断TCP连接是否已经死亡。总结指出,虽然TCP没有提供系统的保活能力,但可以在应用程序里建立这种机制,依赖于系统定时器和恰当的应用层报文协议,比如心跳包。最后,作者留下了两个思考题,引发读者对TCP探活方法适用性和额外探活报文对带宽的影响进行思考。 通过本文,读者可以快速了解TCP连接状态检测的重要性、TCP保活机制的实现方法以及对带宽的影响,为网络编程中连接状态的监测提供了有益的技术参考。
《网络编程实战》,新⼈⾸单¥59
全部留言(46)
- 最新
- 精选
- 传说中的成大大置顶思考题 1. udp不需要连接 所以没有必要心跳包 2. 我觉得还是很有必要判定存活 像以前网吧打游戏 朋友的电脑突然蓝屏死机 朋友的角色还残留于游戏中,所以服务器为了判定他是否真的存活还是需要一个心跳包 隔了一段时间过后把朋友角色踢下线
作者回复: 2是一个很好的例子。
2019-08-28520 - fjpcode1.UDP里面各方并不会维护一个socket上下文状态是无连接的,如果为了连接而保活是不必要的,如果为了探测对端是否正常工作而做ping-pong也是可行的。 2.额外的探活报文是会占用一些带宽资源,可根据实际业务场景,适当增加保活时间,降低探活频率,简化ping-pong协议。 3.多次探活是为了防止误伤,避免ping包在网络中丢失掉了,而误认为对端死亡。
作者回复: 👍
2019-08-28249 - 扩散性百万咸面包想到HTTP Header也能设置Connection: Keep-Alive,也是应用层协议,是不是底层实现也类似于定时器+Ping Pong的思路?
作者回复: HTTP的 keep-alive是为了使http变成长连接,在此前的http 1.0中,每次http的请求-响应之后,tcp连接就会被释放掉,这显然是非常浪费的,于是通过加入keep-alive,使得http连接不会被立即释放。
2020-04-17219 - 满怀老师 我想问一下 看您在回复当中有说 虽然TCP本身的keep-alive机制可以设置保活时间,保活探测时间间隔以及探测次数,但是应用层会无法感知,那么这种情况下会怎么处理呢 就是文中所给出的三种情况吗
作者回复: 是的,大部分的应用程序开发者都会选择自己在应用层处理连接有效性的检测。
2019-12-208 - 蛮野文章中提到保活有两个方向,实际应用中,会有两个方向同时探测的场景吗
作者回复: 当然有。服务器端要探活client来保证自己不会维护无效连接,客户端来探活保持自己是不是可以持续申请资源。
2019-12-178 - 徐凯老师 同步连接可以实现心跳包么 如果不能的话 那同步连接如果因为客户端崩溃 没有通过四次挥手结束连接 服务端还堵塞在接收数据 那么这样如何判断对方已经离开呢
作者回复: 首先,客户端应用程序崩溃是可以有FIN包的,如果有的话,read阻塞就可以返回了;其次,如果真的是客户端机器跪了,那么是没有FIN包发出的,这个时候,我们只好一直在那里傻等。 且慢,还有别的辙,那就是不要用阻塞I/O,不要在哪里傻傻等待。使用I/O复用就可以办到的,往后看就会明白了。
2019-09-0636 - 石将从为啥这句套接字要加1呢?int rc = select(socket_fd + 1, &readmask, NULL, NULL, &tv);
作者回复: 这是因为,嗯,跟select实现有关,我再后面讲select时详细剖析,现在先记住吧。
2019-08-2945 - rongyefeng服务器端恢复心跳包这段 case MSG_PING: { messageObject pong_message; pong_message.type = MSG_PONG; sleep(sleepingTime); ssize_t rc = send(connfd, (char *) &pong_message, sizeof(pong_message), 0); 老师,这个type是int类型,应该将其转为网络序才对吧? pong_message.type = htonl(MSG_PONG); 而且你的客户端程序也是有转换的,是不是服务器端这里忘记了?
作者回复: Bingo。确实是我忘记了:)
2020-05-184 - HunterYuan对于协议栈中的TCP的keep-alive是可以手动配置的,全局配置通过修改net.ipv4下的等参数;局部配置可以通过setsockopt修改socket选项。在工作中遇到过一个oracle,windows服务器的保活时间大于,我们设备状态连接表的保活时间,导致,一段时间后重连,导致服务器报错问题。当时最最快的处理办法是,修改window默认的保活时间小于状态连接失效时间。
作者回复: 学习了。
2019-12-174 - LDxyTCP本身的keep-alive的时间是可以自己设置的吗?如果是可以自己设置的,为何还需要自己实现这个机制?
作者回复: 可以设置的,但是有时候应用层需要感知处理这样的异常
2019-08-284