TCP的三次握手和四次挥手,为什么TCP可靠

一.三次握手过程。

第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认

(请求建立连接。);

SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;

(同意建立连接。)

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

(连接成功,开始进行数据传输。)

RFC793文档里带有SYN标志的过程包是不可以携带数据的,也就是说三次握手的前两次是不可以携带数据的(逻辑上看,连接还没建立,携带数据好像也有点说不过去)。重点就是第三次握手可不可以携带数据。TCP协议建立连接的三次握手过程中的第三次握手允许携带数据

【问题1】为什么TCP采用三次握手而不是两次?

3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
因为两次握手不可靠,举个例子,客户端发送了一个请求建立连接的包,由于网络原因迟迟没有抵达服务器,客户端只能再发一次请求,这次成功抵达并完成了数据传输。过了一段时间,第一次延迟的请求也到达了服务器,服务器并不知道这是无效请求,依旧正常响应,此时如果是两次握手,那么就会建立一条无效的连接,而如果是三次握手,那么客户端就能丢弃这条连接,避免了无谓的网络开销。

再一个例子,假设A向B发送了一个请求连接的包,B接收到向A返回确认连接的时候,此时如果是两次握手B已经认为连接已经建立,但是假如这个确认连接的包因为网络问题出现丢包或者延时到达的问题,实际上A并不认为已经建立了连接,此时如果B向A发送数据分组的时候,并不会有应答分组,因为A认为还没有与B建立连接,而是一直在等待B的建立连接的应答,会忽略B发来的任何数据分组,所以B在自己发出的数据分组超时没有收到应答后,会重复发出,造成死锁

二.四次挥手过程


当要断开TCP连接时,通信两端就会进行4次挥手的操作。由于连接是双向的,所以客户端和服务器都要发送携带FIN标志位的包,才算彻底断开了连接。
1.客户端发送一个携带FIN标志位的包,请求断开连接。
2.服务器响应一个携带ACK标志位的包,同意客户端断开连接。
3.服务器再发送一个携带FIN标志位的包,请求断开连接。
4.客户端最后发送一个携带ACK标志位的包,同意服务器断开连接。

1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

【问题2】为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

TCP为什么可靠

https://blog.csdn.net/Awille/article/details/79748193

 

1、序列号与确认号

当发送错误的时候,会发生:

a、超时重传机制

发送方发送的报文中含有序列号,每当发送一个报文后,就启动一个计时器(RTO),该计时器的时间一般是有当前网络来决定的,一个RTT指的是当一个报文从发送到接收到对应的ACK标志的时间,RTO的决定一般是发送方尝试发送几个报文,然后取平均RTT时间来决定计时器的值。 当发送一个报文以后,发送方在计时范围以内,如果没有接收到相应的ACK确认报文,那么发送方就会重传该报文。

b、快速重传机制

该机制指的是,发送方一直发送报文,不会每发一次报文就都要等待到这个报文的ACK标志才发送下个报文。 当接收方发送接受的序列号不对的时候,发送连续的3个ACK标志,告诉发送方,这个报文在传输过程中出现了丢包。发送方如果接收到某个相同序列号的三个ACK报文,那么此时立马重发该报文,不用等待计时器的时间结束。

2、检验和

通过检验和的方式,接收端可以检测出来数据是否有差错和异常,假如有差错就会直接丢弃TCP段,重新发送。TCP在计算检验和时,会在TCP首部加上一个12字节的伪首部。检验和总共计算3部分:TCP首部、TCP数据、TCP伪首部

3、流量控制(滑动窗口)

发送方通过维持一个发送滑动窗口来确保不会发生由于发送方报文发送太快接收方无法及时处理的问题。此时发送方的报文分为四类, 第一类是已经发送并且得到接收方确认的报文,第二类是已经发送但是没有接收到确认的报文,第三类是发送方还没发送,但是滑动窗口还足够巨大,允许被发送的报文, 第四类是还没发送并且窗口已经被占满,不允许发送的报文。 一般来说,滑动窗口的最左端都是介于第一类跟第二类报文的分界线,最右端是第三类跟第四类报文的分界线。

滑动窗口的流量控制可以包括那么几个协议:

a、停等协议。 滑动窗口的大小为1, 每个发送报文都要等到被确认以后,发送方才继续发送下一个报文。

b、后退n步协议。 该协议下,滑动窗口大于1,发送方可以一直发送报文,但是当接收到接收方发送的三个连续的同一序列号的ACK报文时,说明该序列号的报文是已经丢失的,那么此时重发该丢失报文以及该报文以后的报文(包括那些已经发送的)。

c、选择重传。在后退n步协议当中,如果某个报文丢失。那么将要重新发送这个丢失报文及以后的所有报文(包括已经发送的),选择重传协议不用做此要求,只要重新发送丢失的报文即可。

4、拥塞控制

首先要明白拥塞控制与流量控制有什么不同,流量控制考虑的是单纯的发送方与接收方,这两个在全部网络过程中的两个端点。而拥塞控制考虑的是整个网络。可以想象一下,在流量控制当中,接收方跟发送方考虑的只是自己的报文有没有发送并且被接收的问题,假设现在网络阻塞,在超时重传机制当中,发送方没有发送后在计时器时间内没有接收到确认报文,就立马重新发送报文,这时候对已经拥塞的网络来说,无异于雪上加霜。同样实在拥塞的网络情况下,考虑下快速重传机制,同样是这个道理。所以,针对以上问题,TCP应该要有一个拥塞控制机制,不然,后果不堪设想。

在拥塞控制机制当中,发送方会维护一个滑动发送窗口,该窗口与拥塞控制窗口一般是一样大的,除非受到物理限制,假设网络的承载量是无线的,那么拥塞窗口理论上就可以无线增大,但受现在电脑技术限制,我们可能无法将发送窗口与拥塞窗口变得一样大。

下面说明下几个符号说明:

cwnd:拥塞窗口大小

ssthreshold: 拥塞阈值 (该阈值是对网络状况的一个预估,决定在拥塞窗口多大的时候采取怎样的策略,它的初始化一般是一个估计,一般都会给出)

 

现在可以看下这个拥塞控制机制包括哪几个策略

a、慢启动

此时一般是(记住是一般情况)cwnd<ssthreshold,此时cwnd呈指数形式增长,1、2、4、8、16、32...这种增长趋势

b、拥塞避免

此时一般cwnd>ssthreshold,此时cwnd呈线性增长,32、33、34、35...这种增长趋势

c、拥塞解决

此时一般是遇到了网络拥塞的状况,解决方法是拥塞阈值乘性减即ssthreshold=cwnd/2,cwnd=1,或者ssthreshold=cwnd/2,cwnd=ssthreshold,这两种情况在后面说明

d、快速恢复

一般是启用拥塞结局策略之后,根据不同的情况,进入慢启动或者拥塞避免阶段。

 

下面我们模拟一下发送方发送报文:假设ssthreshold=8

首先肯定是慢启动阶段,cwnd增长,1、2、4、8,到8的时候,cwnd达到了ssthreshold的值,于是进入拥塞避免阶段,cwnd继续增长8、9、10,假设到10的时候,发生了网络拥塞,这时候拥塞分为两种情况:

第一种,发送方接收到同一序列号的报文的连续三个ACK确认报文,说明出现了丢包,但是接收到接收方发送的丢包信号,说明网络情况还是相对较好的,于是此时发送方做出反应,将ssthreshold=cwnd/2=5,cwnd=ssthreshold=5,然后进入拥塞避免阶段,cwnd继续以5、6、7....这种情况增长。

(三个重复ACK,拥塞窗口减半,然后阈值也减半,再线性增长)

第二种,遇到超时Timeout事件,这时候,就说明网络拥塞情况就比较严重了,连接收方发送的丢包信号都不完整了,这个时候得采取更加严厉的措施了,于是ssthreshold=cwnd/2,cwnd=1,然后重新进入慢启动过程。

(拥塞窗口置为1,阈值减半,指数增长到阈值再线性增长)
#TCP和HTTP的区别https://www.cnblogs.com/baizhanshi/p/8482612.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值