1、为什么TCP采用3次握手而不是2次或4次握手
原因1:双向连接,至少要三次握手
其实问题本质是信道不可靠,但是通信双方需要就某个问题达成一致,而要解决这个问题,无论在消息中包含什么消息,三次通信是理论上的最小值。 所以三次握手不是TCP本身的要求,而是为了满足“在不可靠信道上可靠的传输信息”这一需求所导致的。三次达到了,后面想接着握手也好,发数据也好,跟进行可靠信息传输的需求就没关系了。
前提1:TCP协议要保证双方可以通信
即发送端接收端要确认自己发送的信息对方能接收到,对方发送的信息自己能接受到
前提2:在前提1的情况下发送的越少越好
假设 1: 一次握手 即发送端向接受端发送一个包 结论: 发送端无法确认自己发送的信息对方是否收到
假设 2: 两次握手 发送端 发一个包 接收端回一个包 结论:发送端可以确定自己发送的信息能对方能收到 也能确定对方发的包自己能收到,但接收端只能确定 对方发的包自己能收到 无法确定 自己发的包对方能收到 假设3: 三次握手 发送端 发一个 接收端回一个 发送端接收到之后再发一个 结论 这样发送端和接收端就能确定双方可以通信了 所以三次是满足要求的最小值,三次握手这个说法不好,其实是双方各一次握手,各一次确认,其中一次握手和确认合并在一起。
原则上任何数据传输都无法确保绝对可靠,三次握手只是确保可靠的基本需要。双方都需要确认自己的发信和收信功能正常,收信功能通过接受对方信息得到确认,发信功能需要发出信息-》对方回复信息得到确认。需要第三次握手的原因在于 Server 端在第二次握手(发出信息)后并不知道对方是否能够接收、己方的发送功能是否正常。但此时数据的单向通道已经建立,对于 Client 来说,已经确认了 Server 端可以接收信号,因此可以单向给 Server 发送数据了。
原因2:
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。如果两次握手的话,客户端有可能因为网络阻塞等原因会发送多个请求报文,这时服务器就会建立连接,浪费掉许多服务器的资源。
2、为什么tcp建立连接是三次握手,而关闭连接却是四次挥手呢?
原因:保证tcp协议的全双工连接能够可靠关闭
这个我们可以看到和 TCP 建立连接时的原因相同,本质是一样,因为 TCP 是全双工通信,只不过三次握手时的 SYN + ACK 是放在一个报文中了,而四次挥手时,己方 ACK 和 FIN 报文是分开发送的。
这是因为服务端在 LISTEN 状态下,收到建立连接请求的 SYN 报文后,把 ACK 和 SYN 放在一个报文里发送给客户端。 而关闭连接时,当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据, 己方也未必全部数据都发送给对方了,所以己方可以立即 close,也可以发送一些数据给对方后, 再发送 FIN 报文给对方来表示同意现在关闭连接,因此,己方 ACK 和 FIN 一般都会分开发送。
3. 为什么在 TCP 四次挥手中主动关闭的一端 TIME-WAIT 状态必须 等待 2MSL 的时间?
原因有二:
- 一、保证 TCP 协议的全双工连接能够可靠关闭
- 二、保证这次连接的重复数据段从网络中消失
先说第一点,如果 Client 直接 CLOSED 了,那么由于 IP 协议的不可靠性或者是其它网络原因,导致 Server 没有收到 Client 最后回复的 ACK。那么 Server 就会在超时之后继续发送 FIN,此时由于 Client 已经 CLOSED 了,就找不到与重发的 FIN 对应的连接, 最后 Server 就会收到 RST 而不是 ACK,Server 就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致 TCP 协议不符合可靠连接的要求。 所以,Client 不是直接进入 CLOSED,而是要保持 TIME_WAIT,当再次收到 FIN 的时候,能够保证对方收到 ACK,最后正确的关闭连接。 再说第二点,如果 Client 直接 CLOSED,然后又再向 Server 发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达 Server,由于新连接和老连接的端口号是一样的,又因为 TCP 协议判断不同连接的依据是 socket pair,于是,TCP 协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以 TCP 连接还要在 TIME_WAIT 状态等待 2 倍 MSL,这样可以保证本次连接的所有数据都从网络中消失。