TCP主动关闭连接
 
appl: close(), --> FIN FIN_WAIT_1 //主动关闭socket方,调用close关闭socket,发FIN
               <-- ACK FIN_WAIT_2 //对方操作系统的TCP层,给ACK响应。然后给FIN
               <-- FIN
               --> ACK "TIME_WAIT" -- 2MSL timeout -->CLOSED //TIME_WAIT,防止ACK没有给到对方。
 
TCP被动关闭连接
 
               <-- FIN "CLOSE_WAIT" //被动方,收到对方的FIN,处于CLOSE_WAIT状态
               --> ACK //被动方的TCP层,给ACK响应
app2: close(), --> FIN LAST_ACK //被动方调用close,从CLOSE_WAIT转到LAST_ACK 不调close,将一直在CLOSE_WAIT状态。
               <-- ACK --> CLOSED tcp是全双工:: 因此close()关闭读写。 shutdown()可以选择关闭读或写。 time_wait的时间会非常长,因此server尽量减少主动关闭连接。
 
 
int close(int sockfd); int shutdown(int sockfd, int howto); // howto: SHUT_RD, SHUT_WR, SHUT_RDWR
shutdown()函数的两个作用:
close()将描述字的引用计数减1,当引用计数为0时,才关闭socket。
如fork()模式中,父进程在accept()返回后,fork()子进程,由子进程处理connfd,而父进程将close(connfd);但此时父进程的close()并不引发FIN。

shutdown()则不管socket的引用计数,直接发生FIN。
shutdown()可控制read/write两个方向的管道。
SHUT_RD shutdown(sockfd, SHUT_RD);后,来自对端的数据都被确认,然后悄然丢弃。 SHUT_WR half close状态。
 
close()引发的4次交互:(这里的close是client发起的)
 
client server
FIN_WAIT_1 ---- FIN M ------> (Server端操作系统的TCP层响应ACK包)
<---- ACK M+1---- CLOSE_WAIT FIN_WAIT_2 (这里必须调用close,才能从CLOSE_WAIT到LAST_ACK)
<------ FIN N ----- LAST_ACK TIME_WAIT (TIME_WAIT有一个重要的作用就是防止最后一个ACK丢失)
------- ACK N+1 ----------> CLOSE
TIME_WAIT 是主动关闭链接时形成的,等待2MSL时间,约4分钟。

主要是防止最后一个ACK丢失。  由于time_wait的时间会非常长,因此server端应尽量减少主动关闭连接

CLOSE_WAIT是被动关闭链接是形成的 ,

按状态机,我方收到FIN,则由TCP实现发送ACK,因此进入CLOSE_WAIT状态。

但如果我方不执行close(),就不能由CLOSE_WAIT迁移到LAST_ACK,则系统中会存在很多CLOSE_WAIT状态的连接。

此时,可能是系统忙于处理读、写操作,而未将已收到FIN的连接,进行close。此时,recv/read已收到FIN的连接socket,会返回0。

大量TIME_WAIT和CLOSE_WAIT的存在,会产生怎样的影响?

内核维护更多的状态。收到ip包,做hash运算,hlist冲突的概率更大。

1. 首先明确下什么是2MSL: TCP四次挥手断开连接时,主动断开连接的一方(这里我们称为客户端A)在收到对端(这里我们称为服务端B)发送的FIN包后,会立马发送ACK响应包并等待一段时间以确保自己发送的ACK包能够成功通过网络传输到达服务端B端,从而帮助B端正常断开连接(B服务端只有收到自己发出的FIN包对应的ACK包后,才能正常释放资源断开连接),这一等待时间的时长为2MSL,是从客户端A发出ACK包开始计算的,如果A在发送完ACK包后又收到了B端发送的新的FIN包,则会再次发送新的ACK包并重新计时(B端可能会因为超时或丢包等各种原因重新发送FIN包);
2. 其次明确下什么是MSL:MSL 即 Maximum Segment Lifetime,它是任何 TCP segment 在网络上存在的最长时间,超过这个时间的 TCP 报文就会被丢弃,RFC793定义了MSL为2分钟,但这完全是从工程上来考虑的,对于现在的网络,不同操作系统的TCP实现,可以根据具体网络情况配置使用更小的MSL;

3. 再次明确下为什么TCP第四次挥手需要等待2MSL:客户端A等待2MSL可以确保客户端A和服务端B之间的数据包可以完成一个完整的来回的传输即 round trip,所以如果A先前发送的ACK包因为某些原因在网络上丢失了,服务端B在超时没有收到客户端A的ACK包后会重新发送FIN包,2MSL的等待时间能够确保客户端A收到服务端B发送的新的FIN包以发送新的ACK包并重新计时;

4. 最后说下如何在LINUX操作系统中查看和配置MSL: 其实在LINUX操作系统中并没有直接配置 MSL 而是配置了 tcp_fin_timeout,由于 tcp_fin_timeout=2MSL,所以我们可以查看tcp_fin_timeout并据此推断MSL: 可以通过命令 sysctl net.ipv4.tcp_fin_timeout 查看 tcp_fin_timeout,可以通过命令 sysctl -w net.ipv4.tcp_fin_timeout=30 修改 tcp_fin_timeout;

简单概括下,因为网络是不可靠的,数据包在传输过程中可能丢失可能超时可能乱序,所以TCP为了在逻辑的虚拟的连接的基础上提供可靠性,在四次挥手断开连接时主动断开连接的一方需要2MSL的等待时间(当然三次握手和四次挥手,以及连接过程中的确认/累计确认/选择确认等机制,也都是这个原因)

TCP四次挥手也遵循相似的套路。

主动断开的一侧为A,被动断开的一侧为B。

第一个消息:A发FIN

第二个消息:B回复ACK

第三个消息:B发出FIN

此时此刻:B单方面认为自己与A达成了共识,即双方都同意关闭连接。

此时,B能释放这个TCP连接占用的内存资源吗?不能,B一定要确保A收到自己的ACK、FIN。

所以B需要静静地等待A的第四个消息的到来:

第四个消息:A发出ACK,用于确认收到B的FIN

当B接收到此消息,即认为双方达成了同步:双方都知道连接可以释放了,此时B可以安全地释放此TCP连接所占用的内存资源、端口号。

所以被动关闭的B无需任何wait time,直接释放资源。

但,A并不知道B是否接到自己的ACK,A是这么想的:

1)如果B没有收到自己的ACK,会超时重传FiN

那么A再次接到重传的FIN,会再次发送ACK

2)如果B收到自己的ACK,也不会再发任何消息,包括ACK

无论是1还是2,A都需要等待,要取这两种情况等待时间的最大值,以应对最坏的情况发生,这个最坏情况是:

去向ACK消息最大存活时间(MSL) + 来向FIN消息的最大存活时间(MSL)。

这恰恰就是2MSL( Maximum Segment Life)。

等待2MSL时间,A就可以放心地释放TCP占用的资源、端口号,此时可以使用该端口号连接任何服务器。

为何一定要等2MSL?

如果不等,释放的端口可能会重连刚断开的服务器端口,这样依然存活在网络里的老的TCP报文可能与新TCP连接报文冲突,造成数据冲突,

为避免此种情况,需要耐心等待网络老的TCP连接的活跃报文全部死翘翘,2MSL时间可以满足这个需求(尽管非常保守)!

socket close和shutdown的区别,TIME_WAIT和CLOSE_WAIT的更多相关文章

  1. socket链接的关闭连接与close和shutdown的区别

    TCP主动关闭连接 appl: close(), --> FIN FIN_WAIT_1 //主动关闭socket方,调用close关闭socket,发FIN <-- ACK FIN_WAI ...

  2. socket 编程 : shutdown vs close

    TCP/IP 四次挥手 首先作者先描述一下TCP/IP 协议中四次挥手的过程,如果对此已经熟悉的读者可以跳过本节. 四次挥手 这是一个很经典的示例图,众所周知tcp socket 在一个生命周期中有很 ...

  3. TIME_WAIT和CLOSE_WAIT状态区别

    [TIME_WAIT和CLOSE_WAIT状态区别] 常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭. TCP协议规定,对 ...

  4. linux reboot ,shutdown,halt区别

    reboot ,shutdown,halt区别 重启   reboot  和 shutdown -r now  效果是一样的都是重启 区别在于reboot 是重启时,删除所有的进程,为不是平稳的终止他 ...

  5. TIME_WAIT和CLOSE_WAIT的区别

    系统上线之后,通过如下语句查看服务器时,发现有不少TIME_WAIT和CLOSE_WAIT. netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) ...

  6. 服务器TIME_WAIT和CLOSE_WAIT区别及解决方案

    系统上线之后,通过如下语句查看服务器时,发现有不少TIME_WAIT和CLOSE_WAIT. netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) ...

  7. TCP连接(Time_Wait、Close_Wait)说明

    修改Time_Wait和CLOSE_WAIT时间 修改Time_Wait参数的方法 (在服务端修改)Windows下在HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlS ...

  8. TCP连接的TIME_WAIT和CLOSE_WAIT 状态解说【转】

    相信很多运维工程师遇到过这样一个情形: 用户反馈网站访问巨慢, 网络延迟等问题, 然后就迫切地登录服务器,终端输入命令"netstat -anp | grep TIME_WAIT | wc ...

  9. 一次TIME_WAIT和CLOSE_WAIT故障和解决办法

    昨天解决了一个curl调用错误导致的服务器异常,具体过程如下: 里头的分析过程有提到,通过查看服务器网络状态检测到服务器有大量的CLOSE_WAIT的状态. 在服务器的日常维护过程中,会经常用到下面的 ...

  10. TCP之 TIME_WAIT和CLOSE_WAIT 状态 的原因分析和处理

    转自:http://blog.csdn.net/shootyou/article/details/6622226 昨天解决了一个HttpClient调用错误导致的服务器异常,具体过程如下: http: ...

随机推荐

  1. oeasy教您玩转vim - 10 - # 插入新行

    插入新行 回忆上节课内容 i.I 在前面插入文本 a.A 在后面插入文本 o.O 换行插入文本 o 其实是 A 回车 O 其实是 k o O 也是 k A 回车 模式切换小技巧 比如你在一句话的中间, ...

  2. oeasy教您玩转vim - 60- # vim选项

    ​ vim选项 从头开始 这次我们从头开始 从进入vim之前开始 我们可以在终端里面给vim怎么样的参数呢? man vim 这个如果不行的话 要先运行unminimize更新manual 也可以在v ...

  3. oeasy教您玩转vim - 82 - # 函数function

    ​ 函数 function 回忆 关于宏,我们回忆一下 qa 开始录制宏 q 结束录制宏 @a 应用宏 qA 追加录制宏 控制寄存器内容其实就是控制宏 宏还有一些特性 可以多文件执行宏 可以并发运行宏 ...

  4. 计算机网络中的检验和(checksum)(包括计算文件的检验和附有c++代码)

    介绍: 检验和(checksum),在数据处理和数据通信领域中,用于校验目的地一组数据项的和.它通常是以十六进制为数制表示的形式.如果校验和的数值超过十六进制的FF,也就是255. 就要求其补码作为校 ...

  5. JVM系列(一) -浅谈虚拟机的成长史

    一.摘要 众所周知,Java 经过多年的发展,已经从一门单纯的计算机编程语言,发展成了一套成熟的软件解决方案.从互联网到企业平台,Java 是目前使用最广泛的编程语言. 以下这段内容是来自 Java ...

  6. 【服务器】Ubuntu虚拟内存设置

    引子 最近服务器内存老是爆掉,64G的内存对于四五个人同时使用还是有点勉强,上网查询了一下虚拟内存的教程,本博客记录一下方法. swap内存设置 假设你想将swap文件放在/mnt/data/mem目 ...

  7. 机器学习:详解什么是端到端的深度学习?(What is end-to-end deep learning?)

    什么是端到端的深度学习? 深度学习中最令人振奋的最新动态之一就是端到端深度学习的兴起,那么端到端学习到底是什么呢?简而言之,以前有一些数据处理系统或者学习系统,它们需要多个阶段的处理.那么端到端深度学 ...

  8. docker cmd和entrypoint

    FROM scratch 很多镜像都是从他开始 创建自己的centos FROM centos 基于官方的centos开始写 构建自己的centos [root@docker dockerfile]# ...

  9. 【Kafka】01 基于Docker环境的单例Kafka搭建

    安装参考: https://www.cnblogs.com/vipsoft/p/13233045.html 环境安装需要 Zookeeper + Kafka 要学习Kafka还需要繁琐的安装配置,所以 ...

  10. 【Java】【常用类】String

    String表示字符串,Java所有的字符串字面值都是String类的实例实现 String是一个final修饰的类,代表不可变的字符序列 字符串是常量,用双引号表示,值在创建之后不能更改 Strin ...