TCP中的状态转移(三种情况)
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
前言
博主个人社区开发与算法学习社区
博主个人主页Killing Vibe的博客
欢迎大家加入一起交流学习~~
在正常情况下TCP要经过三次握手建立连接四次挥手断开连接但断开连接的时候由于双方的关闭时机不同双方也相应的会有不同的状态。
一、 TCP的生命周期
这里有张图很好的总结了TCP整个生命周期情况一
服务端状态转化
- [CLOSED -> LISTEN] 服务器端调用listen后进入LISTEN状态等待客户端连接
- [LISTEN -> SYN_RCVD] 一旦监听到连接请求同步报文段就将该连接放入内核等待队列中并向客户端发送SYN确认报文。
- [SYN_RCVD -> ESTABLISHED] 服务端一旦收到客户端的确认报文就进入ESTABLISHED状态可以进行读写数据了。
- [ESTABLISHED -> CLOSE_WAIT] 当客户端主动关闭连接调用close服务器会收到结束报文段服务器返回确认报文段并进入CLOSE_WAIT
- [CLOSE_WAIT -> LAST_ACK] 进入CLOSE_WAIT后说明服务器准备关闭连接需要处理完之前的数据当服务器真正调用close关闭连接时会向客户端发送FIN此时服务器进入LAST_ACK状态等待最后一个ACK到来这个ACK是客户端确认收到了FIN
- [LAST_ACK -> CLOSED] 服务器收到了对FIN的ACK彻底关闭连接。
客户端状态转化
- [CLOSED -> SYN_SENT] 客户端调用connect发送同步报文段
- [SYN_SENT -> ESTABLISHED] connect调用成功则进入ESTABLISHED状态开始读写数据
- [ESTABLISHED -> FIN_WAIT_1] 客户端主动调用close时向服务器发送结束报文段同时进入FIN_WAIT_1
- [FIN_WAIT_1 -> FIN_WAIT_2] 客户端收到服务器对结束报文段的确认则进入FIN_WAIT_2开始等待服务器的结束报文段
- [FIN_WAIT_2 -> TIME_WAIT] 客户端收到服务器发来的结束报文段进入TIME_WAIT并发出LAST_ACK
- [TIME_WAIT -> CLOSED] 客户端要等待一个2MSLMax Segment Life报文最大生存时间的时间才会进入CLOSED状态。
二、另外两种挥手情况
当然上面的图只是其中一种情况对应了博主之前讲4次挥手的情况一总共有三种情况。
下面博主给大家带来另外两种变形的情况是不是究极折磨🤔
分别是情况二 和 情况 三 先记住
解析
- 对于情况二是客户端想关闭了发送了个FIN到服务器。服务器收到FIN的同时也刚好想关闭收到了FIN之后把自己的FIN 主动发送了出去顺带了个ACK此时就没有CLOSE_WAIT状态了因为服务器也是主动关闭的客户端也没有了FIN_WAIT 2状态。相比较于情况一
- 对于情况三是服务器在收到客户端发送的FIN 之前也想主动关闭把自己的FIN 主动发送了出去。当处于FIN_WAIT 1状态的端 收到了对方传来的FIN并且要回一个ACK的时候就会进入CLOSING状态。
好有了上述三种情况就可以理解下面的TCP状态汇总图了不理解也无所谓记住挥手阶段有三种情况就行
首先大家握手的状态变化都是一样的区别就在挥手阶段
分了三种情况这里说服务器和客户端是为了好理解
情况一四次挥手服务器是被动关闭的一方客户端主动关闭
情况二三次挥手服务器和客户端都是主动关闭的一方
情况三四次挥手服务器和客户端都是主动关闭的一方。
注意看了下面我说的应该有助于理解
CLOSE_WAIT 状态
留心观察一下三种情况是不是发现这个状态只发生在情况一里面也就是只发生在被动方身上出现在只有一方提出了挥手FIN。
TIME_WAIT状态
留心观察一下这个状态三种情况都有但是只发生在主动方身上出现在基本挥手已经结束的情况。
三、经典四问
好了到这里相信读者们对这个状态转化有了初步了解现在博主有四个问题帮助大家更好理解这些状态
问题一
服务器上出现大量CLOSE_WAIT状态的TCP连接请问这种现象是否合理
答
不确定。单纯这个现象无法明确断言是否正常的。
因为如果我们的程序设计时会出现比较长时间的单方面关闭的情况时出现大量的CLOSE_WAIT是合理现象。
但如果我们没有这种设计则不合理可能的原因是我们这一侧忘记调用socket.close()
问题二
服务器上发现了大量的TIME_WAIT的TCP连接是否合理
答
理论上讲合理就是代码正常的关闭了连接只是主动关闭的TCP连接比较多罢了。
但是实践上来说是不合理的。因为维护连接是有成本的最主要的硬件成本就是内存。
客户端上背负的连接比较少几百条服务器上背负的连接很多几十万-几百万。所以如果让服务器背负这个TIME_WAIT连接的成本相对压力较大所以一般建议让客户端来背这个成本。
所以一般做网络编程设计时不建议服务器去主动关闭连接某些特殊情况下该主动关闭还是得主动的
问题三
既然挥手的工作已经完成了为什么要有个TIME_WAIT状态而不是直接进入CLOSED状态
答
1. 我们不能保证最后一个ACK 接收方一定能收到如果接收方没收到就不能closed就会重发FIN如果发送方没有这个TIME_WAIT状态收到FIN就不能ACK了那接收方就关闭不了了。
2.TCP靠五元组来区分连接五元组就是一条连接的主键信息连接如果没有经过TIME_WAIT释放则五元组就会立即又被分配出去了。如果此时收到了一些之前网络传输比较慢的一些数据就不能判断是谁发过来的了有可能是上一个进程发送的。
问题四
为什么是TIME_WAIT的时间是2MSL
- MSL是TCP报文的最大生存时间因此TIME_WAIT持续存在2MSL的话就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失否则服务器立刻重启可能会收到来自上一个进程的迟到的数据但是这种数据很可能是错误的
- 同时也是在理论上保证最后一个报文可靠到达假设最后一个ACK丢失那么服务器会再重发一个FIN。这时虽然客户端的进程不在了但是TCP连接还在仍然可以重发LAST_ACK
MSL是个理论值实际中很多OS取的是经验值一般取一分钟。所以默认情况下TIME_WAIT的持续时间是2分钟。这个值可以修改。
总结
以上就是TCP状态转移的三种情况觉得有帮助的朋友可以点赞收藏一波有什么疑问可以私信博主。