0
点赞
收藏
分享

微信扫一扫

【Linux】Shell编程

萧萧雨潇潇 2024-02-11 阅读 25

TCP相关知识点

参考:
《计算机网络》
(建议收藏)TCP协议灵魂之问,巩固你的网路底层基础
关于 TCP 三次握手和四次挥手,满分回答在此 (值得看)

TCP处于网络体系结构中的运输层。
运输层主要为应用进程提供端到端的逻辑通信,然后对收到的报文进行差错检测等,它主要有两种不同的运输协议,即面向连接的TCP和无连接的UDP。

UDP

TCP

TCP主要的协议内容:连接管理、流量控制、拥塞控制、差错控制。

  • 序号 seq:TCP 连接中传送的数据流中的每一个字节都按顺序编号(字节数)。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。

  • 确认号ack:期望收到对方的下一个报文段的数据的第一个字节的序号。一般是序号+1。若确认号为 N,则表明:到序号 N-1 为止的所有数据都已正确收到。

  • 数据偏移(首部长度):它指出 TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。

  • 终止 FIN:用来释放一个连接。当 FIN = 1时,表明此报文段的发送发的数据已发送完毕,并要求释放运输连接。

  • RTT是一个报文自发送到接收端返回确认的时间。

连接建立

TCP报文中主要和连接有关的信息是SYN/ACK字段,SYN是同步位,表示这是一个连接请求或者连接接受报文,ACK是一个确认位,当ACK为1时确认号字段才有效。
TCP通过三次握手建立连接。

首先客户端向服务器发出连接请求报文段,其中同步位SYN为1,并生成随机序号 seq = x,表明传送数据时的第一个数据字节的序号是 x。
服务端接收请求后则返回确认报文,同步位SYN=1,确认位ACK=1,确认号(期待收到下一份报文的序号)为x+1,服务端同样生成随机序号为y。
客户端接收到之后知道服务器能接收到自己的信息,但是服务器仍不知道客户端收到没有,因此客户端再次发送第三份报文,同步位SYN=0,确认位ACK=1,确认号(通常为序号+1)y+1,序号(回应期待)x+1。
至此连接正式建立。

四次挥手终止连接

这是由于 TCP 的半关闭(half-close)特性造成的,TCP 提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力,客户端或服务端均可主动发起挥手动作,TCP 连接的释放需要发送四个包(执行四个步骤),因此称为四次挥手。

简而言之:客户端主动关闭TCP连接,首先发送一个结束FIN报文,报文包括序列号x,等待服务端确认,此时客户端处于等待。服务端收到FIN报文后会发送ACK确认报文,并且确认号ack=x+1,序列号为服务器自定的y。此时TCP处于半关闭状态,客户端等待服务端发出的连接释放报文。服务端接收到连接关闭报文后可能需要一段时间处理,处理完毕后向刚才的客户端发送FIN报文,表示自己也可以关闭连接了,第三次发送的报文FIN=1,ACK=1,ack仍然为x+1(确认号同上一次),seq为任意序列号u。客户端接收到后发送ACK报文(ack=u+1,ACK=1,seq=x+1,确认号为请求来的序列号+1,新序列号为请求来的确认号),确保双方都接收到后TCP通道关闭。

tcp的差错控制(校验和、确认和超时重传)

TCP收到包后会检查校验和字段,如果遇到校验和有差错的报文,TCP 直接丢弃,等待重传。

确认:
接收方收到包后会发送一个ACK确认包告知收到并且在序列号中标记下一个希望接收到的序列号开头,TCP中采用“累计确认”、“延迟确认”、“不逐一确认”方式,只要收到一个帧即默认之前序列号的帧都正确收到,并且接收方不用对每一帧进行ACK回复,每隔一段时间才会合并发一个确认帧。

超时重传:
当发送端发送一段字节的数据后,会把这个报文段保存在一个队列中,并启动一个计时器(RTO / 重传计时器 计时器的值是动态确认的,与RTT有关)。

  • 快重传
    在 TCP 传输的过程中,如果发生了丢包,即接收端发现数据段不是按序到达的时候,接收端的处理是重复发送之前的 ACK。
    比如第 5 个包丢了,即使第 6、7 个包到达的接收端,接收端也一律返回第 4 个包的 ACK。
    当发送端超时了仍然没有收到接收端的ack确认,那么发送端会把队列中的首部报文重新发送。或者当发送端收到 3 个重复的 超时重传ACK 时,它可以不等待计时器直接重传报文段,这种机制也称为快重传。

  • 选择性重传
    接收端在发送超时重传ACK时,会在报文的首部带上一个已经接收到的区间数据,因此发送端收到后就可以选择性重传而不是全部重传。

解释如下:
既然要重传,那么只重传第 5 个包还是第5、6、7 个包都重传呢?
当然第 6、7 个都已经到达了,TCP 的设计者也不傻,已经传过去干嘛还要传?干脆记录一下哪些包到了,哪些没到,针对性地重传。
在收到发送端的报文后,接收端回复一个 ACK 报文,那么在这个报文首部的可选项中,就可以加上SACK这个属性,通过left edge和right edge告知发送端已经收到了哪些区间的数据报。因此,即使第 5 个包丢包了,当收到第 6、7 个包之后,接收端依然会告诉发送端,这两个包到了。剩下第 5 个包没到,就重传这个包。这个过程也叫做选择性重传(SACK,Selective Acknowledgment),它解决的是如何重传的问题。

tcp的流量控制(滑动窗口、接收窗口、发送窗口)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
对于发送端和接收端而言,TCP 需要把发送的数据放到发送缓存区, 将接收的数据放到接收缓存区。(缓冲等待队列)
接收缓存区中包含已接收但还未确认的数据和剩余空闲字节数,剩余的空间即为接收窗口。发送缓存区其实就是发送窗口,包含已发送但是未确认的数据和即将发送的数据。



具体例子:
握手建立连接后,双方初始化各自的窗口大小,服务器向客户端发送的报文段中说明接收窗口大小(字节为单位),而发送窗口不能大于接收窗口。

tcp的拥塞控制(慢启动、拥塞避免、快重传、快恢复)

对于拥塞控制来说,TCP 每条连接都需要维护两个核心状态:

  • 拥塞窗口(Congestion Window,cwnd)
  • 慢启动阈值(Slow Start Threshold,ssthresh)
    涉及到的算法有:
  • 慢启动
  • 拥塞避免
  • 快速重传和快速恢复
拥塞窗口(Congestion Window,cwnd)

发送方维持一个叫做拥塞窗口 cwnd (congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。
发送方让自己的发送窗口等于拥塞窗口。如再考虑到接收方的接收能力,则发送窗口还可能小于拥塞窗口。
拥塞窗口(cwnd)和接收窗口(rwnd)用于限制发送窗口的大小。发送窗口大小 = min(rwnd, cwnd)

慢启动和拥塞避免

首先,三次握手,双方宣告自己的接收窗口大小,发送方初始化拥塞窗口(cwnd)大小。
在开始传输的一段时间,发送端每收到一个 ACK(每经过一个 RTT),拥塞窗口大小翻倍。如果说初始窗口为 10,那么第一轮 10 个报文传完且发送端收到 ACK 后,cwnd 变为 20,第二轮变为 40,第三轮变为 80,依次类推。
指数型增长到达慢启动阈值ssthresh后,就会改为线性增长,每收到一个确认帧后窗口大小+1。
指数型增长阶段被称为慢启动,而线性增长阶段被称为拥塞避免。

当网络开始出现拥塞时

丢包后,有两种重传方式,对应不同的网络情况,也就对应着两种拥塞发生时的控制算法:

  • 接收方超时计时器超时
    TCP认为这种情况比较糟糕,调整力度比较大:
  1. 把慢启动阈值设置为出现拥塞时的发送方窗口值的一半(但不能小于2)。
  2. 然后把拥塞窗口 cwnd 重新设置为 1,执行慢开始算法。
  • 快速重传(收到三次重复ACK确认)
    TCP认为现在的网络拥塞情况没有那么严重。
    因此现在不执行慢开始算法,即拥塞窗口 cwnd 现在不设置为 1,而是设置为慢开始门限 ssthresh 减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大。

快重传和快恢复

都是网络拥塞时的处理。
快重传在TCP的超时处理中已经讲过了,就是指如果发送方连续收到三次重复发送的ACK确认报文,可以不理会超时计时器的信息,立即重传对方未接收到的报文段。
快恢复当发送端收到连续三个重复的确认时,就把慢开始门限 ssthresh 减半。但接下去不执行慢开始算法。 由于发送方现在认为网络的拥塞情况没有那么严重,因此现在不执行慢开始算法,即拥塞窗口 cwnd 现在不设置为 1,而是设置为慢开始门限 ssthresh 减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大。

举报

相关推荐

Linux shell编程

Linux shell编程 数组

Linux下Shell编程

linux shell编程作业

Linux 的 shell编程

Linux Shell编程入门

0 条评论