计网回顾---TCP

概念

  • TCP 提供一种面向连接的、可靠的字节流服务
  • 在一个 TCP 连接中,仅有两方进行彼此通信。TCP不能用于广播和多播
  • TCP 使用校验和,确认和重传机制来保证可靠传输
  • TCP 给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复
  • TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制

三次握手

  1. 客户端想要建立连接,给服务器发送建立连接的包(SYN = 1, seq = x)。自己进入SYN_SEND状态
  2. 服务器收到消息后,知道客户端想要建立连接,于是给客户端发送确认应答(ACK = 1, ack = x + 1, SYN = 1, seq = y)。然后自己进入SYN_RCVD状态。
  3. 客户端收到消息后,知道服务器可以建立连接,那么在此发送确认包(ACK = 1, ack = y+1),并进入链接状态。服务器收到后也进入连接状态,这样就建立好连接了。

为什么是三次而不是两次或者四次

首先说一下为什么不是两次?

比方说客户端发起了一个Syn包,但是这个包滞留在了网络中而迟迟没有到达,这样由于TCP的重传机制,他就会又发送一个Syn包过去,这时由于两次握手,这样就建立起了连接。这样看起来确实没问题,但是如果断开连接后,我们滞留在网络中的那个Syn包这时突然到达了服务器中,这时又由于两次握手,所以服务器和客户端建立了连接,但是客户端已经断开了。。。。。

所以这样就出错了,所以就需要三次握手。

那为什么不是四次?

说实话,这个问题有点那啥。。。我三次能稳定的搞定的东西,那我何必四次。

三次握手中可以携带数据吗

第三次可以,前两次不行。

根据协议文档的要求,带有SYN标志的包是不允许携带数据的。

因为前两次还没有建立好连接,那么如果有人想攻击服务器,那么他就可以在第一次握手的SYN报文中放入大量数据,导致服务器必须花费大量时间和资源去处理这些数据,增大了服务器被攻击的风险。

四次挥手

  1. 首先客户端给服务器发送FIN包(FIN = 1, seq = x),告诉服务器我的消息发完了,可以断开连接了,但是仍然可以接收数据。客户端进入FIN_WAIT1。

  2. 服务器收到后,就会发送一条确认信息(ACK = 1, ack = x + 1),告诉客户端自己收到刚刚的消息了,但是还没有准备好关闭连接。服务器进入CLOSE_WAIT,客户端收到后进入FIN_WAIT2

  3. 然后当服务器准备好关闭连接后,就给客户端发送关闭消息(FIN = 1, seq = y),然后自己进入LAST_ACK状态。

  4. 客户端收到后,就知道可以断开连接了,然后就发送一个确认包(ACK = 1, ack = y + 1),然后进入TIME_WAIT状态,服务器收到确认包之后,就断开连接,进入CLOSE状态。

    客户端进入TIME_WAIT状态后,就会等待两个MSL(报文最大生存时间),如果没有收到服务器端的任何消息,就认为服务器端已经正常关闭了,那么自己也会关闭。

https://raw.githubusercontent.com/HIT-Alibaba/interview/master/img/tcp-connection-closed-four-way-handshake.png

为什么要等待两个MSL

如果不等待,客户端直接关闭连接,那么当服务器还有很多数据要发送给客户端,并且还在路上的时候,而此时客户端的接口正好被新的应用占用,那么就接收到了无用的数据包。

那么为什么是两个而不是一个,因为

  • 1个MSL确保四次挥手中的主动关闭方最后的ACK报文能到达对端
  • 另一个MSL确保对端没有收到ACK重传的FIN报文可以到达

累计确认 超时重发 出错重发

首先TCP和UDP都是在传输时会将数据拆分,拆分成一段一段。

对于TCP来说,他会给每个包一个ID,在建立连接的时候就确定起始ID,然后按照ID一个一个发送,为了保证不丢包,每发送一个消息都要进行应答,应答之前的某个ID收到了,这就叫做累计确认或者累计应答。

如果一段时间内没有收到确认消息,就会认为接收方没有收到发过去的这个包,然后就会重发,这就是超时重发机制。

对于每个包都要一个端到端的校验和,如果收到端的校验和有错,那么TCP将丢掉这个包和不确认收到此包,等待发送方重发。

刚刚收到,每个包都会有一个ID,如果没有收到这个ID的包,那么就会重发,这样通过ID保证了有序性。

流量控制

保证有序性

如果发送者发送数据过快,接收者来不及接收,那么就会有分组丢失。为了避免分组丢失,控制发送者的发送速度,使得接收者来得及接收,这就是流量控制。流量控制根本目的是防止分组丢失,它是构成TCP可靠性的一方面。

由滑动窗口协议(连续ARQ协议)实现。滑动窗口协议既保证了分组无差错、有序接收,也实现了流量控制。主要的方式就是接收方返回的 ACK 中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。

滑动窗口协议(连续ARQ协议)

首先双方三次握手,初始化各自的窗口大小,均为 200 个字节。

假如当前发送端给接收端发送 100 个字节,那么此时对于发送端而言,SND.NXT 当然要右移 100 个字节,也就是说当前的可用窗口减少了 100 个字节,这很好理解。

现在这 100 个到达了接收端,被放到接收端的缓冲队列中。不过此时由于大量负载的原因,接收端处理不了这么多字节,只能处理 40 个字节,剩下的 60 个字节被留在了缓冲队列中。

注意了,此时接收端的情况是处理能力不够用啦,你发送端给我少发点,所以此时接收端的接收窗口应该缩小,具体来说,缩小 60 个字节,由 200 个字节变成了 140 字节,因为缓冲队列还有 60 个字节没被应用拿走。

因此,接收端会在 ACK 的报文首部带上缩小后的滑动窗口 140 字节,发送端对应地调整发送窗口的大小为 140 个字节。

此时对于发送端而言,已经发送且确认的部分增加 40 字节,也就是 SND.UNA 右移 40 个字节,同时发送窗口缩小为 140 个字节。


由于停止等待ARQ协议信道利用率太低,所以需要使用连续ARQ协议来进行改善。这个协议会连续发送一组数据包,然后再等待这些数据包的ACK。

发送方采用流水线传输。流水线传输就是发送方可以连续发送多个分组,不必每发完一个分组就停下来等待对方确认。连续ARQ协议通常是结合滑动窗口协议来使用的,发送方需要维持一个发送窗口,如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bZJ0KSBk-1615709507345)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/639af480-4677-49fc-9c59-51e97627a7f3/Untitled.png)]

图(a)是发送方维持的发送窗口,它的意义是:位于发送窗口内的5个分组都可以连续发送出去,而不需要等待对方的确认,这样就提高了信道利用率。

连续ARQ协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。例如上面的图(b),当发送方收到第一个分组的确认,就把发送窗口向前移动一个分组的位置。如果原来已经发送了前5个分组,则现在可以发送窗口内的第6个分组。

规则:

  1. 凡是已经发送过的数据,在未收到确认之前,都必须暂时保留,以便在超时重传时使用。
  2. 只有当发送方A收到了接收方的确认报文段时,发送方窗口才可以向前滑动几个序号。
  3. 当发送方A发送的数据经过一段时间没有收到确认(由超时计时器控制),就要使用回退N步协议,回到最后接收到确认号的地方,重新发送这部分数据。

拥塞控制

它是防止过多的数据注入到网络中,避免出现网络负载过大的情况;常用的方法就是:( 1 )慢开始、拥塞避免( 2 )快重传、快恢复。

慢开始

发送方维持一个拥塞窗口(cwnd)。拥塞窗口的大小取决于网络的拥塞程度,并且动态的变化。

慢开始的思想就是,一开始先别发送大量的数据,而是将cwnd从1开始发送,试探下网络的拥塞程度,然后从小到大的增加拥塞窗口的大小。

比方说:cwnd为1,然后发送方收到接收方返回的确认消息后,cwnd变为2发送,然后收到确认消息后,cwnd变为4。。。核心就是每次扩大2倍。

但是为了防止cwnd增长过大导致的拥塞,还需设置一个慢开始门限ssthresh状态变量:

  • 当cwnd < ssthresh 使用慢开始
  • 当cwnd = ssthresh 慢开始和拥塞避免都可以
  • 当cwnd > ssthresh 使用拥塞避免

拥塞避免

当cwnd > ssthresh时,再使用慢开始,cwnd每次增加一倍,就有点不太妥。这个时候就可以使用拥塞避免,每次把cwnd+1,这样就按线性规律缓慢增长。

但是,不管是在慢开始阶段,还是拥塞避免阶段,只要出现了网络拥塞,就会把ssthresh的值设置为出现拥塞时的发送窗口的一半。然后再把cwnd设置为1,在重新从慢开始开始。

AIMD算法

乘法减小(Multiplicative Decrease)和加法增大(Additive Increase)

“乘法减小”指的是无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞,就把慢开始门限ssthresh设置为出现拥塞时的发送窗口大小的一半,并执行慢开始算法,所以当网络频繁出现拥塞时,ssthresh下降的很快,以大大减少注入到网络中的分组数。“加法增大”是指执行拥塞避免算法后,使拥塞窗口缓慢增大,以防止过早出现拥塞。常合起来成为AIMD算法。

快重传

快重传要求接收方在收到一个失序的报文段后就立即发出重复确认,而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。

比如第 5 个包丢了,即使第 6、7 个包到达的接收端,接收端也一律返回第 4 个包的 ACK。当发送端收到 3 个重复的 ACK 时,意识到丢包了,于是马上进行重传,不用等到一个 RTO 的时间到了才重传。

快恢复

当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半(为了预防网络发生拥塞)。但是接下去并不执行慢开始算法,而是开始拥塞避免算法。

拥塞控制和流量控制都是什么,两者的区别?

  • 拥塞控制:对网络中的路由和链路传输进行速度限制,避免网络过载;包含四个过程:慢启动、拥塞避免、快重传和快恢复
  • 流量控制 :对点和点/发送方和接收方之间进行速度匹配,由于接收方的应用程序读取速度不一定很迅速,加上缓存有限,因此需要避免发送速度过快;相关技术:TCP滑动窗口、回退N针协议
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值