前言
通过查阅知乎,博客以及书籍中的知识点
主要参考的链接也有如下:
TCP 为什么是三次握手,而不是两次或四次?
最主要的原因是:为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误,也就是网络中存在延迟的重复分组
引用谢希仁版《计算机网络》中的例子
“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。
假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了
。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。
理论上讲不论握手多少次都不能确认一条信道是“可靠”的,但通过3次握手可以至少确认它是“可用”的,再往上加握手次数不过是提高“它是可用的”这个结论的可信程度。
TCP 的可靠连接是靠 seq( sequence numbers 序列号)来达成的。
握手机制
两次握手:
-
A 发送同步信号SYN + A初始序列号
-
B发送同步信号SYN + B初始化序列号r + B的ACK序列号
本质上就是双方要连接,要等待对端同意并返回确认,一端请求后收到确认包就意味着,网络可达并且对端同意建立连接。最后的模型则是
A–请求–>B
A<–确认–B
A<–请求–B
A–确认–>B
中间两次可以一起返回,所以是三次
四次握手:(可加第二部第三部合并)
-
A 发送同步信号SYN + A初始序列号
-
B 确认收到A的同步信号,并且命名为B的ACK序列号
-
B发送同步信号SYN + B初始序列号
-
A确认收到B的同步信号命名 ,并且命名为A的ACK序列号
综上所述,三次握手机制为TCP的诞生
三次握手机制:
- 服务器和客户端都为CLOSED状态。双方都得创建各自的传输控制块(TCB)。
- 服务器创建完TCB后遍进入LISTEN状态,此时准备接收客户端发来的连接请求。
客户端向服务端发送连接请求报文段。该报文段的头部中SYN=1,ACK=0,seq=x。请求发送后,客户端便进入SYN-SENT状态。
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答:SYN=1,ACK=1,seq=y,ack=x+1。该应答发送完成后便进入SYN-RCVD状态
当客户端收到连接同意的应答后,还要向服务端发送一个确认报文段,表示:服务端发来的连接同意应答已经成功收到。 该报文段的头部为:ACK=1,seq=x+1,ack=y+1。 客户端发完这个报文段后便进入ESTABLISHED状态,服务端收到这个应答后也进入ESTABLISHED状态,此时连接的建立完成!
补充四次挥手
四次握手和四次挥手的性质不一样
三次握手主要用于建立链接
四次挥手主要用于断开连接
- 客户端发起中断连接请求,发送FIN报文。(具体消息为我没有数据信息发送了,如果2. 你还有数据没发送完,不要着急关闭socket)
服务端端接到FIN报文后,发送ACK(请你继续等待)
客户端就进入FIN_WAIT状态,继续等待服务端端的FIN报文。
- 当客户端端确定数据已发送完成,则向服务端端发送FIN报文
- 客户端收到FIN报文后,发送ACK后进入TIME_WAIT状态,如果服务端没有收到ACK则可以重传。收到就可以断开连接。
客户端等待了2MSL后依然没有收到回复,则证明服务端已正常关闭