(图解)TCP的三次握手,四次挥手
文章目录
- 1. TCP包头结构
- 1.1固定部分字段
- 1.2 可变选项部分字段
- 2. TCP的三次握手与四次挥手
- 2.1 服务器端状态转换
- 2.2 客户端状态转换
- 3. TCP的状态转换图
- 一、状态说明
- 二、状态转换
1. TCP包头结构
TCP(Transmission Control Protocol)
传输控制协议是一种面向连接的、可靠的、基于字节流的传输层协议。TCP报文段头部由长度为20
字节的固定部分和长度可变的选项部分组成.
1.1固定部分字段
- 源端口:占
2字节
,表示发送方的端口号。端口是传输层与应用层的服务接口,传输层的复用和分用功能都要通过端口才能实现。 - 目的端口:占
2字节
,表示发送方的目标端口号。 - 序号:
占4字节
,用于说明该TCP报文段所携带的数据中第一个字节的编号。TCP连接中传送的数据流中的每一个字节都编上一个序号,序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。这是TCP保证数据顺序性的关键字段。 - 确认号:
占4字节
,用来表示希望接受的下一个字节的序号,也表示对方所发送的、在该字节之前的字节已经正确接收。这是TCP保证数据可靠性的重要机制。 - 数据偏移/首部长度:
占4位
,指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。
数据偏移的单位是32位字(以4字节为计算单位),因此最大能表示的数值为15,即TCP报文段首部的长度最长为60字节(15×4字节)。该字段也被称为“首部长度”。 - 保留字段:
占6位
,保留为将来使用,目前的TCP报文段中该字段置为0。 - URG(紧急标志字段):占1位,用于指示紧急指针字段是否有效。当URG=1时,表明紧急指针字段有效,告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。
- ACK(确认标志字段):
占1位
,用于指示确认字段是否有效
。只有当ACK=1时,确认号字段才有效;当ACK=0时,确认号无效。 - PSH(急迫标志字段):
占1位
,用于要求马上发送数据。当PSH=1时,接收TCP收到报文段后,会尽快地交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。 - RST(复位标志字段):
占1位
,用于对本TCP连接进行复位,还可以用于拒绝非法的数据段或数据连接。当RST=1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。 - SYN(同步标志字段):
占1位
,表示同意建立连接的连接相应TCP报文
。当SYN=1时,表示发起一个连接请求或连接接受报文。 - FIN(终止标志字段):
占1位
,用来释放TCP连接。当FIN=1时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。 - 窗口大小:
占2字节
,通过窗口大小字段的值告知对方自己接收窗口大小,用于实现TCP的流量控制和差错恢复
。这个值是本机期望一次接收的字节数。 - 校验和:
占2字节
,校验的范围包括TCP报文段头部、用户数据以及一个伪TCP头部。校验和字段用于保证数据的完整性。 - 紧急指针:
占2字节(或16位
),指出本报文段中紧急数据的最后一个字节的序号(有的说法是字节数)。紧急指针字段仅在URG=1时有效,它是一个偏移量,和序号字段中的值相加可得到紧急数据最后一个字节的序号。
1.2 可变选项部分字段
TCP包头的可变选项部分用于实现除TCP报文段头部指定功能外的扩展功能,其字节长度最大为40字节。常见的TCP选项包括:
- 选项结束(EOP,0x00):占1字节,放在末尾用于填充,表示首部已经没有更多的消息,应用数据在下一个32位字开始处。
- 无操作(NOP,0x01):占1字节,也用于填充,放在选项的开头。
- MSS(最大报文段长度):格式包括种类(1字节,值为2)、长度(1字节,值为4)和数值(2字节)。用于在连接开始时确定MSS的大小,如果没有确定,就用默认的(一般实现是536字节)。MSS告诉对方TCP:“我的缓存所能接收的报文段的数据字段的最大长度是MSS个字节。”
- 窗口扩大因子:格式包括种类(1字节,值为3)、长度(1字节,值为3)和数值(1字节)。当通信双方认为首部的窗口值还不够大的时候,在连接开始时用这个来定义更大的窗口。仅在连接开始时有效,一经定义,通信过程中无法更改。
2. TCP的三次握手与四次挥手
如图
2.1 服务器端状态转换
-
[CLOSED -> LISTEN]
- 服务器端的套接字在调用
listen
函数后,进入LISTEN状态。一旦服务器监听到连接请求(SYN报文段),它会将该连接放入内核的等待队列中,并将套接字的状态从LISTEN改为SYN_RCVD(同步接收)。
- 服务器端的套接字在调用
-
[SYN_RCVD -> ESTABLISHED]
- 当服务器收到客户端的SYN报文并发送了SYN-ACK后,如果成功接收到客户端的ACK确认报文,服务器套接字的状态会从SYN_RCVD变为ESTABLISHED。此时,连接已经建立,服务器和客户端可以开始传输数据。
-
[ESTABLISHED -> CLOSE_WAIT]
- 当客户端主动关闭连接(通过调用close函数),服务器会收到一个FIN报文段(结束报文段)。服务器会发送一个ACK报文段作为确认,并将套接字状态更改为CLOSE_WAIT。这个状态表示服务器已经知道了客户端想要关闭连接,但服务器本身可能还需要处理一些未完成的数据或执行一些清理工作。
-
[CLOSE_WAIT -> LAST_ACK]
当服务器完成所有需要处理的数据或清理工作后,它会调用close函数来关闭连接
。此时,服务器会向客户端发送一个FIN报文段,并将套接字状态更改为LAST_ACK。这个状态表示服务器正在等待客户端对FIN报文段的最后一个ACK确认。
-
[LAST_ACK -> CLOSED]
- 当服务器收到客户端对FIN报文段的ACK确认后,套接字的状态会从LAST_ACK变为CLOSED。此时,连接已经完全关闭,服务器不再保留与该连接相关的任何资源。
2.2 客户端状态转换
-
[CLOSED -> SYN_SENT]
- 当客户端调用connect函数尝试建立连接时,它会发送一个SYN报文段到服务器,并将套接字状态更改为SYN_SENT。这个状态表示客户端已经发送了同步请求,并正在等待服务器的响应。
-
[SYN_SENT -> ESTABLISHED]
- 如果客户端成功接收到服务器的SYN-ACK报文段,并发送了ACK确认报文段,那么套接字的状态会从SYN_SENT变为ESTABLISHED。此时,连接已经建立,客户端可以开始发送数据。
-
[ESTABLISHED -> FIN_WAIT_1]
- 当客户端主动关闭连接(通过调用close函数),它会发送一个FIN报文段到服务器,并将套接字状态更改为FIN_WAIT_1。这个状态表示客户端已经发送了结束请求,并正在等待服务器的确认。
-
[FIN_WAIT_1 -> FIN_WAIT_2]
- 当客户端收到服务器对FIN报文段的ACK确认后,套接字的状态会从FIN_WAIT_1变为FIN_WAIT_2。这个状态表示客户端已经知道了服务器已经收到了结束请求,并正在等待服务器的结束请求。
-
[FIN_WAIT_2 -> TIME_WAIT]
- 当客户端收到服务器的FIN报文段(表示服务器也准备关闭连接)时,它会发送一个ACK确认报文段,并将套接字状态更改为TIME_WAIT。
这个状态是一个等待状态,客户端需要等待足够的时间(通常是2倍的MSL,即报文最大生存时间),以确保所有可能的延迟或重复的报文都被处理完毕
。
- 当客户端收到服务器的FIN报文段(表示服务器也准备关闭连接)时,它会发送一个ACK确认报文段,并将套接字状态更改为TIME_WAIT。
-
[TIME_WAIT -> CLOSED]
- 当等待时间结束后,套接字的状态会从TIME_WAIT变为CLOSED。此时,连接已经完全关闭,客户端可以释放与该连接相关的所有资源。
3. TCP的状态转换图
TCP(Transmission Control Protocol,传输控制协议)的状态转换图描述了TCP连接从建立到终止的整个过程中可能经历的各种状态以及这些状态之间的转换。:
一、状态说明
- CLOSED:初始状态,表示TCP连接未建立或已关闭。
- LISTEN:服务端进入的状态,表示服务端正在监听来自客户端的连接请求。
- SYN_SENT:客户端进入的状态,表示客户端已发送SYN(同步)报文段,用于发起连接请求。
- SYN_RCVD:服务端进入的状态,表示服务端已接收到客户端发送的SYN报文段,并发送了SYN+ACK(同步+确认)报文段作为响应。
- ESTABLISHED:表示TCP连接已经建立成功,客户端和服务端可以进行数据传输。
- FIN_WAIT_1:客户端进入的状态,表示客户端已经发送了连接关闭请求(FIN),等待服务端的确认或进一步数据传输。
- FIN_WAIT_2:客户端进入的状态,表示客户端已经收到了服务端对连接关闭请求的确认(ACK),继续等待服务端发送连接关闭请求。
- CLOSE_WAIT:服务端进入的状态,表示服务端收到了客户端的连接关闭请求(FIN),并已经发送确认(ACK),等待关闭连接。
- TIME_WAIT:表示连接已经关闭,但为了确保网络中所有数据包都被正确处理,等待一段时间(2MSL,最长报文段寿命的两倍)后才彻底释放连接。此外,该状态也出现在双方同时关闭连接,即都发送了FIN报文的情况下。
- LAST_ACK:表示被动关闭的一方在发送FIN报文后,等待对方的ACK报文。注意,虽然在一些资料中LAST_ACK被列为TCP的一种状态,但在某些描述中,它可能被视为CLOSE_WAIT和TIME_WAIT之间的一个过渡阶段,而不是一个独立的状态。不过,为了全面解释,这里仍将其列出。
另外,还有一个较为罕见的状态CLOSING,表示一方发送FIN报文后,并没有收到对方的ACK报文,反而收到了对方的FIN报文。这通常发生在双方几乎同时关闭SOCKET的情况下。
二、状态转换
-
连接建立过程:
- 从CLOSED状态开始,客户端发送SYN报文。
- 服务端收到SYN报文后,回复SYN+ACK报文。
- 客户端收到SYN+ACK报文后,发送ACK报文进行确认。
- 双方进入ESTABLISHED状态,表示连接已建立。
-
连接关闭过程:
- 在数据传输完成后,一方发送FIN报文段,另一方收到后发送ACK确认。
- 发送FIN报文的一方进入FIN_WAIT_1状态(客户端)或CLOSE_WAIT状态(服务端)。
- 根据情况,发送方可能进入FIN_WAIT_2状态,等待对方发送FIN报文。
- 接收方在发送完自己的数据后,发送FIN报文,然后等待对方的ACK确认。
- 双方最终进入TIME_WAIT状态(通常是主动关闭连接的一方),等待2MSL时间后彻底释放连接。
-
特殊情况:
- 在FIN_WAIT_1状态下,如果收到了对方同时带FIN标志和ACK标志的报文,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
- 如果出现异常情况,如网络故障或设备重启,可能导致状态转换不按正常流程进行。