【计算机网络】流量控制、拥塞控制、三次握手、四次挥手

一、流量控制

流量控制是让发送方的发送速率不要太快,让接收方来得及接收。利用滑动窗口机制实现TCP连接上对发送方的流量控制。

TCP采用大小可变的滑动窗口进行流量控制,窗口大小的单位是字节。

发送窗口在连接建立时由双方商定。但在通信的过程中,接收端可根据自己的资源情况,随时动态地调整对方的发送窗口上限值(可增大或减小)。
如果没有这些“窗口”,那么TCP没发送一段数据后都必须等到接收端确认后才能发送下一段数据,这样做的话TCP传输的效率实在是太低了。
解决的办法就是在发送端等待确认的时候继续发送数据,假设发送到第X个数据段是收到接收端的确认信息,如果X在可接受的范围内那么这样做也是可接受的。这就是窗口(缓冲区)引入的缘由。
1.1 窗口
(1) 接收端窗口 rwnd     
接收端缓冲区大小。接收端将此窗口值放在 TCP 报文的首部中的窗口字段,传送给发送端。
(2) 拥塞窗口 cwnd (congestion window)    
发送端缓冲区大小
(3) 发送窗口swnd
发送窗口的上限值 = Min [rwnd, cwnd]
当 rwnd < cwnd 时,是接收端的接收能力限制发送窗口的最大值。
当 cwnd < rwnd 时,则是网络的拥塞限制发送窗口的最大值。 
1.2 滑动窗口
发送端已发送了 400 字节的数据,但只收到对前 200 字节数据的确认,同时窗口大小不变。还可发送 300 字节。

发送端收到了对方对前 400 字节数据的确认,但对方通知发送端必须把窗口减小到 400 字节。现在发送端最多还可发送 400 字节的数据。

二、拥塞避免

2.1 慢开始和拥塞避免

2.1.1 慢开始原理
(1)在主机刚刚开始发送报文段时可先将拥塞窗口 cwnd 设置为一个最大报文段 MSS 的数值。
(2)在每收到一个对新的报文段的确认后,将拥塞窗口增加至多一个 MSS 的数值。
(3)用这样的方法逐步增大发送端的拥塞窗口 cwnd,可以使分组注入到网络的速率更加合理。
2.1.2 实例讲解
 
 
注:图中窗口的单位都是报文段
(1)当 TCP 连接进行初始化时:
发送窗口:swnd = 1 
慢开始阈值:ssthresh = 16
(2)发送端收到 ACK1 (确认 M0,期望收到 M1)后,将 cwnd 从 1 增大到 2,于是发送端可以接着发送 M1 和 M2 两个报文段(指数增长)
(3)接收端发回 ACK2 和 ACK3。发送端每收到一个对新报文段的确认 ACK,就把发送端的拥塞窗口加 1。现在发送端的 cwnd 从 2 增大到 4,并可发送 M4 ~ M6共 4个报文段。(指数增长)
(4)当swnd >= ssthresh,swnd执行拥塞避免算法,swnd窗口按线性规律增长。 (加法增大)
(5)当发送 超时,此时swnd = 24 :
ssthresh = swnd/2 = 12;(乘法减小)
swnd = 1
(6)重复地2步。
2.2 快重传和快恢复
2.2.1 快重传
发送端只要一连收到三个重复的 ACK 即可断定有分组丢失了,就应立即重传丢失的报文段而不必继续等待为该报文段设置的重传计时器的超时
2.2.2 快恢复
(1) 当发送端收到连续三个重复的 ACK 时,就重新设置慢开始门限 ssthresh。
(2) 与慢开始不同之处是 swnd 不是设置为 1,而是设置为 ssthresh + 3 * MSS。 
(3) 若收到的重复的 ACK 为 n 个(n > 3),则将 cwnd 设置为 ssthresh + n * MSS。
(4) 若发送窗口值还容许发送报文段,就按拥塞避免算法继续发送报文段。
(5) 若收到了确认新的报文段的 ACK,就将 swnd 缩小到 ssthresh。

三、三次握手和四次挥手

TCP在传输之前会进行三次沟通,一般称为“三次握手”,传完数据断开的时候要进行四次沟通,一般称为“四次挥手”。

两个序号和三个标志位:

  (1)序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
  (2)确认序号:ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。
  (3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:
  (A)URG:紧急指针(urgent pointer)有效。
  (B)ACK:确认序号有效。
  (C)PSH:接收方应该尽快将这个报文交给应用层。
  (D)RST:重置连接。
  (E)SYN:发起一个新连接。
  (F)FIN:释放一个连接。

 需要注意的是:
  (A)不要将确认序号ack与标志位中的ACK搞混了。
  (B)确认方ack=发起方req+1,两端配对。

(1)在第一次消息发送中,A随机选取一个序列号x作为自己的初始序号发送给B,同时SYN标志位为1代表发起连接;

(2)第二次消息B使用ACK=1对A的数据包进行确认,因为已经收到了序列号为x的数据包,准备接收序列号为x+1的包,所以ack=x+1,同时B告诉A自己的初始序列号,就是seq=y

(3)第三条消息A告诉B收到了B的确认消息并准备建立连接,A自己此条消息的序列号是x+1,所以seq=x+1,而ack=y+1是表示A正准备接收B序列号为y+1的数据包

四次挥手:

由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,

收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。

首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。

(1)客户端首先发送连接释放报文,这个报文首部FIN=1,序列号seq=u(等于前面传过来的数据最后一个字节的序号+1),此时客户端进入FIN-WAIT-1状态,等待服务器确认。TCP规定,FIN报文段即使不带数据,也要消耗一个序号。

(2)服务器收到释放报文段后发出确认,确认号ack=u+1,这个报文段自己的序号是v(等于服务器传送的数据最后一个字节的序号+1),此时服务器进入CLOSE-WAIT状态,此时处于半关闭状态,即客户端已经不发送数据了,但服务器要发送数据,客户端也得接收。(时长是CLOSE-WAIT的长度)

(3)客户端接收到服务器的确认后,进入FIN-WAIT-2状态,等待服务器发送连接释放报文。

(4)服务器如果没有要发送的数据,就可以发送连接释放报文,FIN=1,假定序号为w(因为在半关闭状态服务器可能会发送数据),服务器要重复上次收到的确认序号ack=u+1,此时服务器进入LAST-ACK状态。

(5)客户端收到服务器发来的连接释放报文,在报文中将ACK=1表示收到确认,确认号ack=w+1表示是对序号为w的确认,自己的序号是seq=u+1,此时客户端进入TIME-WAIT状态。但是此时TCP连接还没有释放,必须经过2MSL(最长报文段寿命的两倍)后,客户端撤销相应的TCB之后,才进入CLOSED状态。

(6)服务器收到了客户端的确认之后,立即进入CLOSED状态。撤销了TCB之后,TCP连接就结束了。

 

为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,

站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,

应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次

而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。

第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。

客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。

这样新的连接中不会出现旧连接的请求报文。

为什么建立连接是三次握手,关闭连接确是四次挥手呢?

建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。

 
非原创,参考文章:

 

转载于:https://www.cnblogs.com/JAVALLiuLei/p/9510233.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值