这是一个被各大厂运维面试问烂的一道题了,不知道你是否还能记得起来
那首先回答这个问题,就需要明白,三次握手的核心目标就是为了在客户端和服务端之间建立起可靠的连接。
什么是连接呢?
连接指在网络中两个或者多个设备之间建立的通信路径。是数据收、发双方在内存中建立的用于维护数据传输状态的对象。比如双方IP,端口,发了多少数据,状态机是否正常,传输速率是多少?等等
所以,这个问题实际在回答为什么三次握手才可以初始化Socket、序列号和窗口大小并建立 TCP 连接
原因一:避免资源浪费
如果只有两次握手,客户端发送SYN之后,服务收到SYN之后回复ACK之后,服务端就会进入ESTABLISHED状态。
当客户端的 SYN 请求连接在网络中阻塞,客户端没有接收到 ACK 报文,就会重新发送 SYN ,由于没有第三次握手,服务器不清楚客户端是否收到了自己发送的建立连接的 ACK 确认信号,所以每收到一个 SYN 就只能先主动建立一个连接,那服务端的资源会迅速被消耗殆尽。
那如果碰上了攻击,可以想象咱们的服务端的连接会迅速被占满。
两次握手会造成资源浪费
即两次握手会造成消息滞留情况下,服务器重复接受无用的连接请求 SYN 报文,而造成重复分配资源。
原因二:避免历史连接
三次握手的主要原因是为了防止旧的重复连接初始化造成混乱。
TCP为了保证数据的可靠性,会重复发送数据,这些数据包往往并不是如我们期望的一样,先发送的数据包,就先到达目标主机,可能会由于网络拥堵等原因,会使得旧的数据包,先到达目标主机,那么这种情况下 TCP 三次握手是如何避免的呢?
客户端连续发送多次 SYN 建立连接的报文:
- 旧SYN比新SYN早到达了服务端;
- 那么此时服务端就会回一个 SYN + ACK 报文给客户端;
- 客户端收到SYN+ACK后会根据序列号,或者超时时间判断这是一个过期的报文,那么客户端就会发送 RST,重置连接。
如果是两次握手连接,就不能判断当前连接是否是历史连接,三次握手则可以在客户端(发送方)准备发送第三次报文时,客户端因有足够的上下文来判断当前连接是否是历史连接:
- 如果是历史连接(序列号过期或超时),则第三次握手发送的报文是 RST 报文,以此中止历史连接;
- 如果不是历史连接,则第三次发送的报文是 ACK 报文,通信双方就会成功建立连接;
所以, TCP 使用三次握手建立连接的最主要原因是防止历史连接初始化了连接。
原因三:同步双方初始序列号
TCP 协议的通信双方, 都必须维护一个序列号, 序列号是可靠传输的一个关键因素,它的作用:
- 接收方可以去除重复的数据
- 接收方可以根据数据包的序列号按序接收
- 可以标识发送出去的数据包中, 哪些是已经被对方收到的
可见,当客户端发送携带初始序列号的 SYN 报文的时候,需要服务端回一个 ACK 应答报文,表示客户端的 SYN 报文已被服务端成功接收,那当服务端发送初始序列号给客户端的时候,依然也要得到客户端的应答回应,这样一来一回,才能确保双方的初始序列号能被可靠的同步。
为什么不是四次握手?
TCP是全双工的,在客户端发送SYN的时候,服务端就需要回复ACK的确认报文,告诉客户端你发的SYN包我收到了;服务端也是需要发送SYN包,携带自己的初始序列号信息,那客户端也需要对这个SYN包回复ACK表示,服务端你发的SYN我也收到了。
从上图可以看到服务端发送ACK和SYN是可以合并到一个数据包中的,也就是我们常说的SYN+ACK. 也就是合并成了三次握手
写在最后
运维相关岗位面试时涉及到知识面非常广,所以复习起来会有无从下手的感觉。为了让同学们面试不迷茫,都能找到一份好工作,我们整理了运维面试的高频面试题,关注我们回复“面试题”免费领取。
如果对您有用,麻烦点赞加关注哦,关注的宝子最帅哦 ^ _ ^