关于TCP

唯愿你平安顺遂~


各位宝宝,最近还好吗?现在疫情还不容乐观,生活就是这样疾苦相伴但我们还得做那个身披铠甲与生活厮杀的勇敢者啊~ 唯愿你平安顺遂~

直接进入正题吧!

建立连接三次握手


假设主动发送请求的一端成为客户端,被动连接的一端为服务端。不管是客户端还是服务端,TCP连接建立完后都能发送和接受数据,所以TCP是一个全双工的协议。

起初,两端是SLOSED状态。在通信开始前,双方都会创建TCB。服务器创建完TCB后便进入LISTEN状态,此时开始等待客户端发送数据。

第一次握手

客户端向服务端发送连接请求报文段(包含自身的数据通讯初始序号)。发送请求后,客户端便进入SYN-SENT状态。

第二次握手

服务端收到连接请求报文段后,如果同意连接,则会发送一个应答(包含自身的数据通讯初始序号)。发送完成后便进入SYN-RECEIVED状态。

第三次握手

客户端收到连接同意的应答后,还会向服务端发送一个确认报文。客户端发完这个报文后就进入ESTABLISHED状态,服务端收到这个应答后也进入ESTABLISHED状态,此时连接建立成功。

tip:第三次握手中可以包含数据,通过快速打开技术(TFO)就可以实现这一功能。客户端和服务端存储相同的cookie,下次握手时发出cookie达到减少RTT的目的。

RTT : 发送端从发送数据到接收到对端数据所需的往返时间。

断开连接四次握手


TCP是全双工的,在断开连接时两端都需要发送FIN和ACK。

第一次握手

若客户端A认为数据发送完成,则它需要向服务端B发送连接释放请求。

第二次握手

B收到连接释放请求后,会告诉应用层要释放TCP链接。然后发送ACK包,并进入CLOSE_WAIT状态,此时A到B的连接已经释放,不再接受A发的数据了。但是TCP连接时双向的,所以B仍然能发送数据到A。

第三次握手

B如果此时还有没发完的数据会继续发送,完毕后向A发送连接释放请求,然后B进入LAST-ACT状态。

tip:通过延迟确认技术,可以将第二次和第三次握手合并,延迟ACK包的发送。

第四次握手

A收到释放请求后,向B发送确认应答,此时A进入TIME-WAIT状态。该状态会持续2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃)时间,若该段时间段内没有B的重发请求,就进入CLOSE状态。当B收到确认应答后,也便进入SCLOSE状态。

(A要进入TIME-WAIT状态,等待2MSL时间后才进入CLOSE状态,why?)

为了保证B能收到A的确认应答。若A发完确认应答后直接进入CLOSE状态,如果确认应答没有网络问题一直没有收到,那么会造成B不能正常关闭。

ARQ协议


ARQ协议也就是超时重传协议。通过确认和超时机制保证了数据的正确送达,ARQ协议包含停止等待ARQ和连续ARQ两种协议。

停止等待ARQ

正确传输过程

只要A向B发送一段报文,都要停止发送并启动一个定时器,等待对端回应,在定时器时间内接收到对端应答就取消定时器并发送下一段报文。

报文丢失或出错

在报文传输过程中会出现丢包。这时候超过定时器设定的时间就会再次发送丢失的数据指导对端响应,所以需要每次都备份发送的数据。

即使报文正常的传输到对端,也可能出现在传输过程中报文出错的问题。这时候对端会抛弃该报文并等待A端重传。

一般一个定时器设定的时间都会大于一个RTT的平均时间。

ACK超时或丢失

对端传输的应答也可能出现丢失或超时的情况。超过定时器时间A端照样会重传报文。这时候B端收到相同序号报文会丢弃该并重传应答,知道A端口发送下一个序号的报文。

在超时的情况也可能出现应答很迟到达,这是A端会判断该序号是否已经接受过,如果接受过只需要丢弃应答即可。

但是在良好的网络环境中,每次发送数据都需要等待片刻肯定是不高效的。

连续ARQ

在连续ARQ中,发送端拥有一个发送窗口,可以在没有收到应答的情况下持续发送窗口内的数据,相比停止等待ARQ减少了等待时间,提高了效率。

累计确认

收到多个报文以后统一回复一个应答报文。报文中的ACK标志位可以用来告诉发送端这个序号之前的数据已经全部接收到了,下次请求这个序号之后的数据。

滑动窗口


在TCP中,两端其实都维护着窗口:分别为发送端窗口和接收端窗口。

发送端窗口包含已发送但未收到回应的数据和可以发送但未发送的数据。

发送端窗口是由接受窗口剩余大小决定的。接收方会把当前接收窗口的剩余大小写入应答报文,发送端根据这个值和当前网络拥塞情况设置发送窗口的大小,所以发送窗口的大小是不断变化的。

当发送端接收到应答报文后,会随之将窗口进行滑动

滑动窗口帮助TCP实现了流量控制的作用。从而保证接收方来得及接受数据,防止出现接收方带宽已满,但是发送方还一直发送数据的情况。

Zore窗口

发送报文过程中,对端出现零窗口的情况。这时候,发送端会停止发送数据,并启动persistent timer。然后会定时发送请求给对端,让对端告知窗口大小。在重试超过一定次数之后,可能会中断TCP连接。

拥塞处理


流量控制是作用于接收方,保证接收方来得及接收数据

拥塞处理作用于网络,防止过多的数据拥塞网络,避免出现网络负载过大

拥塞处理包括四个算法:慢开始、拥塞避免、快速重传、快速恢复

慢开始算法

在传输开始时将发送窗口慢慢指数级扩大,防止开始时传输大量数据导致网络拥塞。

具体步骤:

  1. 连接初始设置拥塞窗口为1MSS(一个分段的最大数据量)
  2. 每个RTT就将窗口大小乘2
  3. 要有一个阈值限制,当窗口大小大于阈值就会启动拥塞避免算法

拥塞避免算法

每过一个RTT窗口大小只加一,这样能够避免指数级增长导致网络拥塞,慢慢将大小调整到最佳值。

步骤:

  1. 将阈值设置为当前拥塞窗口的一半
  2. 将拥塞窗口设为1MSS
  3. 启动拥塞避免算法

快速重传

快速重传一般与快恢复一起出现。一旦接收端收到的报文出现失序的情况,接收端只会回复最后一个顺序正确的报文序号。如果发送端收到三个重复的ACK,无需等待定时器超时而是直接启动快速重传算法

总结:

- 建立连接需要三次握手,断开连接需要四次握手

- 滑动窗口解决了数据的丢包,顺序不对和流量控制问题

- 拥塞避免解决了对流量的控制,保证在全天候环境下最优的传递数据

愿我们有能力不向生活缴械投降---Lin

本文分享自微信公众号 - 女程序员的日常(gh_df41d619fb70),作者:凛

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-02-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • V8引擎对Array.prototype.push的源码实现

    一直非常困惑操作arguments的时候为什么都要用Array.prototype,今天终于明白了。

    用户3258338
  • 随便做的svg动画

    2. 以上情况下atrributeName = "height"会被微信公众号的富文本编辑器过滤掉(出现在百叶窗那个例子中)

    用户3258338
  • 读书笔记-《了不起的nodejs》-2

    大家好,今天刚学会用微信的图文模板,啊哈哈,以后文章就要这样排版喽!哈哈,解锁新功能,有点小开心,我还真是一个容易满足的人呢!各位宝宝,也要做一个容易满足的人...

    用户3258338
  • 速读原著-TCP/IP(慢启动)

    迄今为止,在本章所有的例子中,发送方一开始便向网络发送多个报文段,直至达到接收方通告的窗口大小为止。当发送方和接收方处于同一个局域网时,这种方式是可以的。但是如...

    cwl_java
  • TCP中有哪些定时器?

    打开窗口ACK丢失的危害:当接收方通告了一个窗口为非0的ACK,此ACK由于某种原因丢失,此时发送方在永远的等窗口打开的通知,接收方则永远的在等新数据的到来,这...

    爬蜥
  • 速读原著-TCP/IP(TCP的坚持定时器)

    我们已经看到 T C P通过让接收方指明希望从发送方接收的数据字节数(即窗口大小)来进行流量控制。如果窗口大小为 0会发生什么情况呢?这将有效地阻止发送方传送数...

    cwl_java
  • 速读原著-TCP/IP(成块数据的吞吐量)

    让我们看一看窗口大小、窗口流量控制以及慢启动对传输成块数据的 T C P连接的吞吐量的相互作用。

    cwl_java
  • tcp中的常见定时器

    (1)超时重传定时器 tcp的靠谱特性,通过确认机制,保证每一个包都被对方收到,那么什么时候需要重传呢?就是靠这个超时重传定时器,每次发送报文前都启动这个定时...

    用户1215536
  • 如何在 Scala 中科学地操作 collection(一)集合类型与操作

    在日常项目开发中,我们几乎都会用到Scala中的集合以及一些集合操作。由于 Scala 中的集合操作灵活多变,对于刚接触Scala的开发者,在选用何种集合以及使...

    Albert陈凯
  • 什么是CNN?写给小白的机器学习入门贴,Facebook员工打造,47k访问量

    那是因为在图像分类时,面临着图像大,物体的形态、位置不同等问题,这就给普通的神经网络带来了难题。

    量子位

扫码关注云+社区

领取腾讯云代金券