网络编程中 TCP 半开连接和TIME_WAIT 学习
https://blog.csdn.net/chrisnotfound/article/details/80112736
上面的链接就是说明来 SO_KEEPALIVE 选项 为什么还需要 在应用层开发 心跳协议的原因 包括分布式系统开发中也必须自己设计 应用层 心跳协议的开发
熟悉基于TCP协议进行linux高性能、高并发服务端编程的朋友肯定应该知道每个文件描述符及其所占的资源对并发量的影响。
在这种7*24甚至*365不间断运行的服务器上,一个描述符被浪费,两个被浪费...如果被浪费的多了,那还何谈高并发,高性能。除去文件描述被正常占用的情况外,是什么导致了我们可用的文件描述符越来越少呢?
https://blog.csdn.net/gettogetto/article/details/76736371
什么是半开连接?
当客户端与服务器建立起正常的TCP连接后,如果客户主机掉线(网线断开)、电源掉电、或系统崩溃,服务器进程将永远不会知道(通过我们常用的select,epoll监测不到断开或错误事件),如果不主动处理或重启系统的话对于服务端来说会一直维持着这个连接,任凭服务端进程如何望穿秋水,也永远再等不到客户端的任何回应。这种情况就是半开连接,浪费了服务器端可用的文件描述符。
如何处理?
熟悉套接字通用选项的朋友一定已经有了想法。TCP套接字不是有个保持存活选项SO_KEEPALIVE嘛,如果在两个小时之内在该套接字的任何一个方向上都没数据交换,TCP就自动给对端发送一个保持存活探测分节,如果此TCP探测分节的响应为RST,说明对端已经崩溃且已经重新启动,该套接字的待处理错误被置为ECONNRESET,套接字本身则被关闭。如果没有对此TCP探测分节的任何响应,该套接字的处理错误就被置为ETIMEOUT,套接字本身则被关闭。
确实,这个选项确实可以处理我们前面遇到的TCP半开连接的问题,但是默认两小时间隔探测的实时性是不是差了些呢?
当然,我们可以通过修改内核参数改小时间间隔,完美了吧?
但是必须注意的是大多数内核是基于整个内核维护这些时间参数的,而不是基于每个套接字维护的,因此如果把无活动周期从两小时改为(比如)2分钟,那将影响到该主机上所有开启了此选项的套接字。
我想大家都不会愿意承担服务器端的这种不确定性吧。另外,心跳除了说明应用程序还活着(进程存在,网络畅通),更重要的是表明应用程序能正常工作。而SO_KEEPALIVE由操作系统负责探查,即便是进程死锁或有其他异常,操作系统也会正常收发TCP keepalive消息,而对方无法得知这一异常。
没关系,其实我们可以在应用层模拟SO_KEEPALIVE的方式,用心跳包来模拟保活探测分节。
由于服务器通常要承担成千上万的并发连接,所以肯定是由客户端在应用层进行心跳来模拟保活探测分节,客户端多次收不到服务器的响应时可终止此TCP连接,而服务端可监测客户端的心跳包,若在一定时间间隔内未收到任何来自客户端的心跳包则可以终止此TCP连接,这样就有效避免了TCP半开连接的情况。
在进行TCP高并发服务器开发时,有些规则仿佛是约定俗成的,很多朋友会依据这些规则去做,比如高并发TCP服务器中进行主动关闭的一方最好是客户端、服务器端程序最好启用SO_REUSEADDR选项,但是很多人却不知所以然,我们为什么要这么做呢?
先上图
可以看到执行主动关闭端和被动关闭端的各个阶段的状态,今天咱的重点就是TIME_WAIT状态,可以看出TIME_WAIT状态是执行主动关闭的那一端产生的。
TIME_WAIT状态有两个存在的理由
可靠地实现TCP全双工连接的终止;
允许老的重复分节在网络中消逝;
第一个理由参考上图。 假设主动关闭端最终发送的ACK丢失了。对端将重新发送FIN,主动关闭端只有在维护状态信息的情况下才可以重新发送最终的那个ACK。如果不维护这个状态信息,主动关闭端将会响应一个RST,对端会将此响应标记为错误,所以不能进行正常的关闭。
第二个理由假设我们在ip A:端口B主机和ip C:端口D主机之间建立一个TCP连接。我们关闭这个连接,过一段时间在相同的IP地址和端口之间建立另一个连接。由于他们的IP地址和端口号都相同,所以如果上一个连接的老的重复分组再出现会影响新的连接。为了做到这一点,TCP将不会给处于TIME_WAIT状态的连接发起这个新的连接。这个持续时间如果大于MSL(IP数据报在因特网中的最大生存时间)
如果要满足以上实现,TIME_WAIT状态必须要有一定的持续时间,所以TIME_WAIT也被称为2MSL等待状态,一般持续时间在1分钟到4分钟之间。
高并发TCP服务器中进行主动关闭的一方最好是客户端:因为对于高并发服务器来说文件描述符资源是很重要的资源,如果对于每一个连接都要经历TIME_WAIT这个2MSL的时长,势必造成资源不能立马复用的浪费。虽然对于客户端来说TIME_WAIT状态会占用端口和句柄资源,但是客户端一般很少有并发资源限制,所以客户端执行主动关闭是比较合适的。
服务器端程序最好启用SO_REUSEADDR选项:我们想这样做一种情况,如果生产环境中服务端程序由于某种错误操作关闭了,我们肯定是要立马重启服务程序,但是TIME_WAIT还在占用着这些地址端口资源让你的服务起不来,那你着不着急。SOREUSEADDR这个选项正是允许地址端口的重复绑定。
网络编程中 TCP 半开连接和TIME_WAIT 学习的更多相关文章
- unp第七章补充之TCP半开连接与半闭连接
半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Duplex)协议,因此这里的半连接"半"字就是相对于全双工的"全&q ...
- TCP半开连接与半闭连接
半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Duplex)协议,因此这里的半连接"半"字就是相对于全双工的"全&q ...
- 网络编程中TCP基础巩固以及Linux打开的文件过多文件句柄的总结
1.TCP连接(短链接和长连接) 什么是TCP连接?TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议. 当网络通信 ...
- Linux系统网络编程中TCP通讯socket--send导致进程被关闭
https://blog.csdn.net/dsanmux/article/details/52083403 https://blog.csdn.net/u011425939/article/deta ...
- [转帖]关于网络编程中MTU、TCP、UDP优化配置的一些总结
关于网络编程中MTU.TCP.UDP优化配置的一些总结 https://www.cnblogs.com/maowang1991/archive/2013/04/15/3022955.html 感谢原作 ...
- 浅谈TCP/IP网络编程中socket的行为
我认为,想要熟练掌握Linux下的TCP/IP网络编程,至少有三个层面的知识需要熟悉: 1. TCP/IP协议(如连接的建立和终止.重传和确认.滑动窗口和拥塞控制等等) 2. Socket I/O系统 ...
- 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
[Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...
- 用java网络编程中的TCP方式上传文本文件及出现的小问题
自己今天刚学java网络编程中的TCP传输,要用TCP传输文件时,自己也是遇到了一些问题,抽空把它整理了一下,供自己以后参考使用. 首先在这个程序中,我用一个客户端,一个服务端,从客户端上传一个文本文 ...
- Fixed-Length Frames 谈谈网络编程中应用层(基于TCP/UDP)的协议设计
http://blog.sina.com.cn/s/blog_48d4cf2d0101859x.html 谈谈网络编程中应用层(基于TCP/UDP)的协议设计 (2013-04-27 19:11:00 ...
随机推荐
- (十五)、linux软件的安装与查询-rpm与yum命令
一.RPM软件管理程序:rpm 1.RPM安装软件(install) rpm命令的选项超级多,安装话直接使用-ivh即可,其余做了解即可 命令格式:rpm -ivh package_name.rp ...
- ArrayList的删除姿势你都知道了吗
引言 前几天有个读者由于看了<ArrayList哪种遍历效率最好,你真的弄明白了吗?>问了个问题普通for循环ArrayList为什么不能删除连续重复的两个元素?其实这个描述是不正确的.正 ...
- STM32串口中断的一些资料
在研究STM32串口接收发送中断的时候找到不少不错的资料,现在备份在这里.以供自己查阅,以及方便其他人. TC ====TXE 顺便预告下最近会写个有关串口处理数据的帖子,从查询和中断方面以及数据处理 ...
- git基础-git别名
Git 并不会在你输入部分命令时自动推断出你想要的命令. 如果不想每次都输入完整的 Git 命令,可以通过 git config 文件来轻松地为每一个命令设置一个别名. 这里有一些例子你可以试试: $ ...
- mysql The used table type doesn’t support FULLTEXT indexes 解决方案 (phpstudy 会出现),coten不会
mysql The used table type doesn't support FULLTEXT indexes 是不支持全文索引,解决方案: 1.停掉mysql服务2.打开my.ini,搜索de ...
- 神经网络中的降维和升维方法 (tensorflow & pytorch)
大名鼎鼎的UNet和我们经常看到的编解码器模型,他们的模型都是先将数据下采样,也称为特征提取,然后再将下采样后的特征恢复回原来的维度.这个特征提取的过程我们称为"下采样",这个恢复 ...
- Python解释器和IPython
目录 简介 Python解释器 IPython 魔法函数 运行和编辑 Debug History 运行系统命令 简介 今天给大家介绍一下Python的一个功能非常强大的解释器IPython.虽然Pyt ...
- MySQL学习Day01
1.MySQL的层级关系 2.xampp的安装使用 如果之前安装过mysql那么就需要将原来的mysql完全卸载干净 1.卸载之前安装的MySQL 安装xampp需要先卸载之前的mysql,以及更改m ...
- Python基础语法6-冒泡排序
用for循环实现冒泡排序(升序): array = [3,2,1] for i in range(len(array) - 1, 0, -1): for j in range(0, i): if ...
- mysqlbinlog :unknown variable 'default-character-set=gbk'
mysqlbinlog :unknown variable 'default-character-set=gbk' 解决方法: 在命令行中加入--no-defaults开关,使用mysqlbinlo ...