SYN
(Synchronize)和ACK
(Acknowledge)是TCP协议中用于连接建立和数据传输的两个非常重要的标志位。
建立一个 TCP 连接需要“三次握手”,缺一不可:
-
一次握手:client客户端发送带有 SYN(SEQ=x) 标志的数据包 -> 服务端,然后客户端进入 SYN_SEND 状态,等待服务器的确认;
-
发起方:客户端
-
描述:客户端选择一个初始序列号
x
,然后发送一个SYN报文段到服务器,该报文段中的序列号字段的值就是这个x
。此时,客户端进入SYN_SENT状态。 -
数据包标志:SYN=1, ACK=0
-
二次握手:server服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 –> 客户端,然后服务端进入 SYN_RECV 状态
-
发起方:服务器
-
描述:服务器接收到客户端的SYN报文段后,需要回应确认。为此,它选择一个初始序列号
y
,并使用x+1
作为确认号(表示服务器期望接收的下一个字节的序列号)。此时,服务器进入SYN_RECEIVED状态。 -
数据包标志:SYN=1, ACK=1
-
三次握手:client客户端发送带有 ACK(ACK=y+1) 标志的数据包 –> 服务端,然后客户端和服务器端都进入ESTABLISHED 状态,完成 TCP 三次握手。
-
发起方:客户端
-
描述:客户端收到服务器的SYN-ACK报文段后,会再次发送一个ACK报文段给服务器。该报文段的确认号应为
y+1
,表示客户端期望接收的下一个字节的序列号。此时,客户端进入ESTABLISHED状态。完成上述三次握手后,服务器也进入ESTABLISHED状态,这时TCP连接建立成功,双方都可以开始发送数据。 -
数据包标志:SYN=0, ACK=1
如何理解客户端发送:SYN,服务器响应:SYN-ACK,客户端再次响应:ACK?
理解TCP的三次握手中的SYN
、SYN-ACK
和ACK
步骤的关键在于明确这个过程的目的:确保两台计算机(通常被称为客户端和服务器)都准备好双向通信。
下面是对这三个步骤的更深入解释:
-
客户端发送:SYN
-
当客户端希望与服务器建立一个新的TCP连接时,它会发送一个SYN(Synchronize)报文段。
-
这个SYN报文段包含一个客户端选择的初始序列号(假设为
x
)。 -
通过这个SYN报文段,客户端实际上在告诉服务器:“我想与你建立连接,并从序列号
x
开始传输数据”。
-
-
服务器响应:SYN-ACK
-
服务器收到客户端的SYN报文段后,为了确认并响应这个连接请求,服务器会发送一个SYN-ACK(Synchronize-Acknowledge)报文段。
-
这个SYN-ACK报文段包含两个关键的信息:
-
ACK:它确认了服务器已经收到了客户端的SYN报文段。这个确认号将是
x+1
,表示服务器已经准备好接收序列号为x+1
的客户端数据。 -
SYN:服务器同样选择一个初始序列号(假设为
y
)来开始它的数据传输。通过这个SYN,服务器告诉客户端:“我也准备好了,并从序列号y
开始传输数据”。
-
-
-
客户端再次响应:ACK
-
客户端收到服务器的SYN-ACK报文段后,需要向服务器确认它已经收到了这个响应。
-
客户端发送一个ACK(Acknowledge)报文段,确认号是
y+1
,表示客户端已经准备好接收序列号为y+1
的服务器数据。
-
简化来说,这个三次握手过程实现了以下目标:
-
确保客户端能够发送数据到服务器(通过SYN报文段)。
-
确保服务器能够接收客户端的数据并发送数据到客户端(通过SYN-ACK报文段)。
-
确保客户端能够接收服务器的数据(通过ACK报文段)。
完成这三个步骤后,TCP连接被建立,并且双方都可以开始双向通信。
为什么要用三次?而不是四次和两次?
因为既要保证数据可靠传输,又要提高传输的效率,而用三次恰恰可以满足以上两方面的需求!
二次握手的过程
-
假设使用二次握手:客户端发送
SYN
,服务器回复SYN-ACK
,然后连接建立。 -
问题是:如果客户端的
SYN
报文段在网络中延迟了,并在很长时间后突然到达了服务器,那么服务器可能会误认为这是一个新的连接请求,并建立一个不需要的连接。而客户端可能早已放弃或建立了新的连接。这会导致服务器浪费资源。 -
结论:二次握手不足以解决“旧报文段”的问题。
断开一个 TCP 连接则需要“四次挥手”,缺一不可:
-
第一次挥手:客户端发送一个 FIN(SEQ=x) 标志的数据包->服务端,用来关闭客户端到服务器的数据传送。然后客户端进入 FIN-WAIT-1 状态。
FIN从主动关闭方到被动关闭方:
-
-
当一个端(例如客户端)完成了数据发送并决定关闭连接时,它会发送一个FIN(Finish)标志的报文段到另一端(例如服务器)。这意味着:“我已经完成了数据发送,不再发送更多的数据”。
-
客户端进入
FIN_WAIT_1
状态。
-
-
第二次挥手:服务器收到这个 FIN(SEQ=X) 标志的数据包,它发送一个 ACK (ACK=x+1)标志的数据包->客户端 。然后服务端进入 CLOSE-WAIT 状态,客户端进入 FIN-WAIT-2 状态。
ACK从被动关闭方到主动关闭方:
-
-
服务器收到这个FIN报文段后,会发送一个ACK(Acknowledge)来确认已收到此FIN报文段。这意味着:“我知道你想关闭连接”。
-
客户端接收到ACK后,进入
FIN_WAIT_2
状态,等待服务器发送它的FIN报文段。 -
服务器此时还可以继续发送数据。
-
-
第三次挥手:服务端发送一个 FIN (SEQ=y)标志的数据包->客户端,请求关闭连接,然后服务端进入 LAST-ACK 状态。
FIN从被动关闭方到主动关闭方:
-
-
当服务器发送完所有数据后,它也会发送一个带有FIN标志的报文段,表示:“我已经完成了数据发送,也不再发送更多的数据”。
-
服务器进入
LAST_ACK
状态。
-
-
第四次挥手:客户端发送 ACK (ACK=y+1)标志的数据包->服务端,然后客户端进入TIME-WAIT状态,服务端在收到 ACK (ACK=y+1)标志的数据包后进入 CLOSE 状态。此时如果客户端等待 2MSL 后依然没有收到回复,就证明服务端已正常关闭,随后客户端也可以关闭连接了。
ACK从主动关闭方到被动关闭方:
-
客户端收到服务器的FIN报文段后,会发送一个ACK报文段来确认。
-
客户端进入
TIME_WAIT
状态,持续一段时间(通常是2倍的MSL,最大报文寿命),以确保ACK报文段能够被服务器接收。这段时间也是为了处理可能在网络中延迟的数据包。 -
服务器收到这个ACK报文段后,关闭连接,进入
CLOSED
状态。 -
当客户端的
TIME_WAIT
计时器到期后,它也进入CLOSED
状态。
注意:虽然经常说客户端和服务器,但TCP四次挥手在任何一端都可以开始。主动发起关闭连接的端被称为“主动关闭方”,而另一端为“被动关闭方”。
这个四次挥手过程确保了双方都能确认连接的终止,并确保双方都已完成数据传输。
-
只要四次挥手没有结束,客户端和服务端就可以继续传输数据!
为什么要四次挥手?
TCP 是全双工通信,可以双向传输数据。任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了 TCP 连接。
举个例子:A 和 B 打电话,通话即将结束后。
-
第一次挥手:A 说“我没啥要说的了”
-
第二次挥手:B 回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话
-
第三次挥手:于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”
-
第四次挥手:A 回答“知道了”,这样通话才算结束。
为什么不能把服务器发送的 ACK 和 FIN 合并起来,变成三次挥手?
因为服务器收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复 ACK,表示接收到了断开连接的请求。等到数据发完之后再发 FIN,断开服务器到客户端的数据传送。
如果第二次挥手时服务器的 ACK 没有送达客户端,会怎样?
客户端没有收到 ACK 确认,会重新发送 FIN 请求。
标签:ACK,报文,面经,SYN,TCP,计网,服务器,FIN,客户端 From: https://www.cnblogs.com/bgDvpNotes/p/17783103.html