TCP状态转换

本文为阅读《TCP/IP详解 卷1 第2版》第13章13.5节的个人知识整理。

TCP在连接的不同阶段需要发送不同类型的报文段而决定TCP在不同阶段应该做什么的是TCP连接所处的状态决定的。

状态转换图:
TCP状态转换图
以下是简略版本的TCP在一个连接过程中的状态转换图:
与正常连接的建立和终止相关的TCP状态

TCP连接建立阶段

由上图可以看出,客户端(一般是主动打开TCP连接的一方)在发送SYN置位的报文段后状态变为SYN_SENT,等到接收到对方的ACK回答以及SYN置位的报文并发送ACK响应服务端后,状态变为ESTABLISHED,表示已经做好了传输数据的准备。而服务端一开始是处于LISTEN监听状态的,在接收到客户端SYN置位的TCP请求并发送自己的SYN置位携带自己的初始序列号的ACK应答报文后状态变为SYN_RCVD,接收客户端的ACK应答后变为ESTABLISHED,TCP连接建立成功,进入数据传输阶段。

TCP连接关闭阶段

主动关闭一方

数据传输完成后,一方主动关闭TCP连接(在图中的例子是客户端主动关闭,但其实服务端也可以主动关闭TCP连接,甚至还可以双方同时关闭)。图中客户端主动发送FIN置位的表示关闭TCP连接的报文后,客户端的TCP状态变为FIN_WAIT_1,收到服务端的ACK响应后变为FIN_WAIT_2(这里可以支持一个半关闭的操作,如果客户端不准备再往服务端发送消息,但是希望继续接收服务端的消息,是可以在FIN的报文中说明希望半关闭的,那样服务端还会继续往客户端发送报文,知道服务端发送FIN置位的报文,但是这样的情况并不多见)。在接收到服务端的FIN置位报文段后客户端TCP状态变为TIME_WAIT(出现在主动关闭一方),发送服务端的FIN报文的响应,在此状态等待两倍最大段生存期的时间后,状态变为CLOSED,TCP连接关闭。

非主动关闭一方

而服务端这边在收到客户端发来的FIN报文,状态变为CLOSE_WAIT,然后发送对客户端FIN报文的ACK响应报文,状态不变,再发送服务端希望关闭连接的FIN报文后,状态变为LAST_ACK,等待接收响应服务端发送的FIN报文的ACK,最后状态变为CLOSED,TCP连接成功关闭。

关于TIME_WAIT状态

等待的作用

在该状态中,TCP将会等待两倍于最大段生存期的时间,有时也被称为“加倍等待”。这么做的目的是防止最后发送的ACK丢失。因为处于LAST_ACK状态的一方会不断的重传FIN报文,直到它收到ACK响应,若是主动关闭的一方在收到FIN并发送ACK后就进入了CLOSED状态,而ACK在传输过程中丢失导致被动关闭的一方无法进入CLOSED,即使重发FIN报文也不会有响应(或者是响应一个重置报文段?),为了解决这个问题,所以主动关闭的一方必须在TIME_WAIT状态等待一段时间,确保被动关闭的一方能接收到ACK从而变为CLOSED状态。

时间等待错误

当TCP处于TIME_WAIT状态时(被动关闭方已经进入CLOSED状态),若此时服务端有一个迟到的TCP报文到达处于TIME_WAIT状态的客户端,客户端会发现该报文的序列号已经过期,但还是会发送一个带最新序列号的ACK给已经是CLOSED状态的服务端,服务端由于已经关闭此TCP连接,所以理所当然的没有关于这个报文的信息,因此发送一个重置报文段作为响应,而这个重置报文段会使还在等待计时器跑完两倍最大段生存期时间的处于TIME_WAIT状态的客户端提前进入CLOSED状态(书上说许多系统规定处于TIME_WAIT状态时不对重置报文段作出反应,从而避免这个问题,但是具体是哪些系统书上也没说…)

副作用

这个TIME_WAIT状态也造成了另一个影响,就是主动关闭一方(通常是客户端)在主动关闭连接后立刻重启客户端,新的客户端也不能重新使用和刚刚被关闭的客户端相同的端口(因为还处于TIME_WAIT状态,无法建立新的连接)。但是由于客户端一般是使用系统分配的随机的端口,所以影响并不大,但对于服务端来说就有一定影响了(因为服务端的某些服务一般使用特定端口,比如apache监听80端口)。

引用\[1\]:Linux内核实现了很多重要的体系结构属性。在或高或低的层次上,内核被划分为多个子系统。Linux也可以看作是一个整体,因为它会将所有这些基本服务都集成到内核中。这与微内核的体系结构不同,后者会提供一些基本的服务,例如通信、I/O、内存和进程管理,更具体的服务都是插入到微内核层中的。\[2\]为了解决这些缺陷,Linux内核开发人员所做的一件事就是使内核模块可以在运行时加载和卸载,这意味着您可以动态地添加或删除内核的特性。这不仅可以向内核添加硬件功能,还可以包括运行服务器进程的模块,比如低级别虚拟化,但也可以替换整个内核,而不需要在某些情况下重启计算机。\[3\] 根据引用\[1\]和引用\[3\]的内容,Linux内核采用了宏内核的机制,将所有的代码和子系统打包到一个文件中。这意味着内核中的每一个函数都可以访问到内核中的其他部分。同时,Linux内核也支持模块的动态装卸,可以在运行时加载和卸载内核模块,从而动态地添加或删除内核的特性。 关于TCP状态转换的内核原理,具体的实现细节可能涉及到更多的技术细节。但是可以简单地说,TCP状态转换是指TCP连接在不同的状态之间进行转换,例如建立连接、数据传输、连接关闭等。在Linux内核中,TCP状态转换是通过TCP协议栈的实现来完成的。TCP协议栈是Linux内核中的一个子系统,负责处理TCP连接的建立、维护和关闭等操作。具体的实现细节可以参考Linux内核的源代码和相关文档。 总结起来,Linux内核采用了宏内核的机制,将所有的代码和子系统打包到一个文件中,并支持模块的动态装卸。TCP状态转换是通过TCP协议栈的实现来完成的。 #### 引用[.reference_title] - *1* *2* *3* [一文看懂Linux内核!Linux内核架构和工作原理详解](https://blog.youkuaiyun.com/qq_40989769/article/details/113388892)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值