在正常情况下,TCP 要经过三次握手建立连接,四次挥手断开连接
服务端状态转化:
客户端状态转化:
三次握手有啥用 ? 和可靠性有什么关系 ?
举个栗子:
以打电话为例, 这个过程就是在检验通信双方的发送能力和接收能力:
假如说小明麦克风坏了,喂了几次没回应,就会重传,重试几次还没回应就放弃。
为啥是三次握手,两次行不行? 四次行不行 ?
服务端状态转化:
客户端状态转化:
为什么还要 TIME_WAIT ?
为的是给最后一次 ACK 提供重传机会,表面上 A 发送完 ACK 后就没有 A 的事了,按理说 A 可以销毁连接了,但是怕最后一个 ACK 丢包,若最后一个 ACK 丢了,那么 B 一定会因为没收到 ACK 重传 FIN,如果 A 已经销毁连接了,那么就无人能够处理这个 FIN 了,因此 A 不应该释放的太早,要等待一段时间,确保 B 不会重传 FIN 后再真正的销毁连接。
为什么是TIME_WAIT的时间是2MSL?
MSL 是 TCP 报文的最大生存时间,因此 TIME_WAIT 持续存在 2MSL 的话
就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失
(否则立刻客户端立即重新创建连接时,可能会收到来自上一个进程的迟到的数据(FIN),但是这种数据很可能是错误的);
同时也是在理论上保证最后一个报文可靠到达
(假设最后一个ACK丢失,那么服务器会再重发一个FIN。这时虽然客户端的进程不在了,但是 TCP 连接还在,仍然可以重发 LAST_ACK );
CLOSE_WAIT
一般而言,对于服务器上出现大量的 CLOSE_WAIT 状态,原因就是服务器没有正确的关闭 socket,没有执行到 socket.close 导致四次挥手没有正确完成。这是一个 BUG。只需要加上对应的 close 即可解决问题。
三次握手一定是客户端发起的(主动发起请求的一方叫做客户端)
四次握手可能是客户端发起的,也有可能是服务器主动发起的
三次握手,中间有两次合并和,
四次握手,中间两次合并不了,不能合并的原因在于 B (被动接收 FIN 的那一方)发送 ACK 和 FIN 的时机不同,
<1> 四次挥手中,B 发送给 A 的 ACK 是由操作系统内核负责的(除了应用层,TCP/IP … 本身就是属于操作系统层面),那么意味着,当内核收到 FIN 后会立即返回 ACK (我们是感知不到的)
<2> B 发送给 A 的 FIN,是由用户代码负责的,B 中代码调用了 socket.close() 方法时才触发 FIN 发送,所以要等到用户代码执行到 socket.close() 方法才触发,但是什么时候发送 取决于用户代码,若 <1> <2> 操作之间的时间差较大,就不能合并了,若时间差较小,由于 延时应带和捎带应答 机制,可能会合并。
而三次握手中 B 发送的 ACK 和 SYN 都是由内核负责的,是同一时机所以能够合并。
好啦! 以上就是对 TCP 三次握手 与 四次挥手的讲解,希望能帮到你 !
评论区欢迎指正 !