计算机网络攻略(3)TCP 三次握手

文章目录

  • TCP 三次握手
    • 为什么是三次握⼿?不是两次、四次?
    • 为什么客户端和服务端的初始序列号 ISN 是不相同的?

TCP 三次握手

TCP 是⾯向连接的协议,所以使⽤ TCP 前必须先建⽴连接,⽽建⽴连接是通过三次握⼿来进⾏的。

计算机网络攻略(3)TCP 三次握手_第1张图片

⼀开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端⼝,处于 LISTEN 状态;

客户端会随机初始化序号( client_isn ),将此序号置于 TCP ⾸部的「序号」字段中,同时把 SYN 标志位置为 1 ,表示 SYN 报⽂。接着把第⼀个 SYN 报⽂发送给服务端,表示向服务端发起连接,该报⽂不包含应⽤层数据,之后客户端处于 SYN-SENT 状态。

服务端收到客户端的 SYN 报⽂后,⾸先服务端也随机初始化⾃⼰的序号( server_isn ),将此序号填⼊TCP ⾸部的「序号」字段中,其次把 TCP ⾸部的「确认应答号」字段填⼊ client_isn + 1 , 接着把 SYN 和 ACK 标志位置为 1 。最后把该报⽂发给客户端,该报⽂也不包含应⽤层数据,之后服务端处于 SYN-RCVD 状态。

客户端收到服务端报⽂后,还要向服务端回应最后⼀个应答报⽂,⾸先该应答报⽂ TCP ⾸部 ACK 标志位置为 1 ,其次「确认应答号」字段填⼊ server_isn + 1 ,最后把报⽂发送给服务端,这次报⽂可以携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态。

服务器收到客户端的应答报⽂后,也进⼊ ESTABLISHED 状态。

从上⾯的过程可以发现第三次握⼿是可以携带数据的,前两次握⼿是不可以携带数据的,这也是⾯试常问的题。

⼀旦完成三次握⼿,双⽅都处于 ESTABLISHED 状态,此时连接就已建⽴完成,客户端和服务端就可以相互发送数据了。

为什么是三次握⼿?不是两次、四次?

在前⾯我们知道了什么是 TCP 连接:
⽤于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括Socket、序列号和窗⼝⼤⼩称为连接。

所以,重要的是为什么三次握⼿才可以初始化Socket、序列号和窗⼝⼤⼩并建⽴ TCP 连接。

接下来以三个⽅⾯分析三次握⼿的原因:

  • 三次握⼿才可以阻⽌重复历史连接的初始化(主要原因)
  • 三次握⼿才可以同步双⽅的初始序列号
  • 三次握⼿才可以避免资源浪费

原因⼀:避免历史连接

三次握⼿的⾸要原因是为了防⽌旧的重复连接初始化造成混乱。

⽹络环境是错综复杂的,往往并不是如我们期望的⼀样,先发送的数据包,就先到达⽬标主机,反⽽它很骚,可能会由于⽹络拥堵等乱七⼋糟的原因,会使得旧的数据包,先到达⽬标主机,那么这种情况下 TCP 三次握⼿是如何避免的呢?

客户端连续发送多次 SYN 建⽴连接的报⽂,在⽹络拥堵情况下:

⼀个「旧 SYN 报⽂」⽐「最新的 SYN 」 报⽂早到达了服务端;

那么此时服务端就会回⼀个 SYN + ACK 报⽂给客户端;

客户端收到后可以根据⾃身的上下⽂,判断这是⼀个历史连接(序列号过期或超时),那么客户端就会发送RST 报⽂给服务端,表示中⽌这⼀次连接。

如果是两次握⼿连接,就不能判断当前连接是否是历史连接,三次握⼿则可以在客户端(发送⽅)准备发送第三次报⽂时,客户端因有⾜够的上下⽂来判断当前连接是否是历史连接:

如果是历史连接(序列号过期或超时),则第三次握⼿发送的报⽂是 RST 报⽂,以此中⽌历史连接;

如果不是历史连接,则第三次发送的报⽂是 ACK 报⽂,通信双⽅就会成功建⽴连接;

所以,TCP 使⽤三次握⼿建⽴连接的最主要原因是防⽌历史连接初始化了连接。

原因⼆:同步双⽅初始序列号
TCP 协议的通信双⽅, 都必须维护⼀个「序列号」, 序列号是可靠传输的⼀个关键因素,它的作⽤:

接收⽅可以去除重复的数据;
接收⽅可以根据数据包的序列号按序接收;
可以标识发送出去的数据包中, 哪些是已经被对⽅收到的;

可⻅,序列号在 TCP 连接中占据着⾮常重要的作⽤,所以当客户端发送携带「初始序列号」的 SYN 报⽂的时候,需要服务端回⼀个 ACK 应答报⽂,表示客户端的 SYN 报⽂已被服务端成功接收,那当服务端发送「初始序列号」给客户端的时候,依然也要得到客户端的应答回应,这样⼀来⼀回,才能确保双⽅的初始序列号能被可靠的同步。

计算机网络攻略(3)TCP 三次握手_第2张图片

四次握⼿其实也能够可靠的同步双⽅的初始化序号,但由于第⼆步和第三步可以优化成⼀步,所以就成了「三次握⼿」。
⽽两次握⼿只保证了⼀⽅的初始序列号能被对⽅成功接收,没办法保证双⽅的初始序列号都能被确认接收。

原因三:避免资源浪费

如果只有「两次握⼿」,当客户端的 SYN 请求连接在⽹络中阻塞,客户端没有接收到 ACK 报⽂,就会重新发送 SYN ,由于没有第三次握⼿,服务器不清楚客户端是否收到了⾃⼰发送的建⽴连接的 ACK 确认信号,所以每收到⼀个 SYN 就只能先主动建⽴⼀个连接,这会造成什么情况呢?

如果客户端的 SYN 阻塞了,重复发送多次 SYN 报⽂,那么服务器在收到请求后就会建⽴多个冗余的⽆效链接,造成不必要的资源浪费。

即两次握⼿会造成消息滞留情况下,服务器重复接受⽆⽤的连接请求 SYN 报⽂,⽽造成重复分配资源。

⼩结

TCP 建⽴连接时,通过三次握⼿能防⽌历史连接的建⽴,能减少双⽅不必要的资源开销,能帮助双⽅同步初始化序列号。序列号能够保证数据包不重复、不丢弃和按序传输。

不使⽤「两次握⼿」和「四次握⼿」的原因:
「两次握⼿」:⽆法防⽌历史连接的建⽴,会造成双⽅资源的浪费,也⽆法可靠的同步双⽅序列号;
「四次握⼿」:三次握⼿就已经理论上最少可靠连接建⽴,所以不需要使⽤更多的通信次数。

为什么客户端和服务端的初始序列号 ISN 是不相同的?

如果⼀个已经失效的连接被重⽤了,但是该旧连接的历史报⽂还残留在⽹络中,如果序列号相同,那么就⽆法分辨出该报⽂是不是历史报⽂,如果历史报⽂被新的连接接收了,则会产⽣数据错乱。

所以,每次建⽴连接前重新初始化⼀个序列号主要是为了通信双⽅能够根据序号将不属于本连接的报⽂段丢弃。

另⼀⽅⾯是为了安全性,防⽌⿊客伪造的相同序列号的 TCP 报⽂被对⽅接收。

学自小林coding《图解网络》,侵删

你可能感兴趣的:(计算机网络,tcp/ip,网络,网络协议)