首页 > 其他分享 >TCP的十个核心机制!

TCP的十个核心机制!

时间:2024-07-04 16:28:54浏览次数:25  
标签:窗口 重传 ACK 应答 十个 TCP 发送 机制

前言

本文主要介绍TCP的十个核心机制,但是这不意味着TCP只有十个机制,只是最核心的十个而已。


补充内容

TCP的6位标志位:

URG: 紧急指针是否有效;

ACK: 确认号是否有效;

PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读⾛;

RST: 对方要求重新建立连接,我们把携带RST标识的称为复位报⽂段;

SYN: 请求建立连接;我们把携带SYN标识的称为同步报⽂段;

FIN: 通知对方,本端要关闭了,我们称携带FIN标识的为结束报⽂段。


一、确认应答

网络中数据传输存在“后发先至”的情况,所以确认应答可以保证TCP的可靠性。可靠性指的不是数据100%到达对方,而是尽可能的传输数据过去。

因此,发送端发送数据,接收端会返回一个应答报文(TCP6个标志位的ACK报文),以确认自己接收到了数据。再通过引入“序号”和“确认序号”,建立应答报文和传输数据之间的关系。

二、超时重传

超时重传是对确认应答的补充,应对网络中数据传输过程中丢包的情况。

超时重传也就是通过重传的方式,将丢包的数据重传一次。在一定时间内,如果接收端没有收到应答报文,那么就会被视为丢包。但是这个“一定时间”不是规定的固定时间,它是动态变化的,随着重传轮次的增加进一步变长,重传频率依次降低。但是达到一定次数的时候,就会触发“重置报文”,也就是TCP6个标志位的RST报文,如果还不行,就会释放连接。(这个就是最坏的情况)

然而发送端无法区分丢包是因为数据丢了还是应答报文丢了,这两种方式都会引发超时重传。针对应答报文丢了的情况,接收端会收到重复的数据,因此接收端会有一个“接收缓冲区”,在TCP层面上对上述数据去重。

并且,接收缓冲区不仅可以去重,还可以对接收到的数据进行排序,确保发送的数据和接收的数据保持一致。

因此超时重传也可以保证TCP的可靠性。

三、连接管理

TCP经过三次握手建立连接,四次挥手断开连接。

  • 握手:发送一个不携带业务数据的数据报,不起任何业务的作用,只是用来“打招呼”。

建立连接就是通信双方各自保存对端的信息,完成连接建立就需要三次握手。这个过程中, 第一次握手一定是客户端向服务器发起。TCP的6个标志位中的ACK和SYN分别为1。SYN里面保存建立连接的双方信息。

三次握手的目的:①,在正式传输业务数据之前,先确认一下通信链路是否通畅;②,验证双发的接收能力和发送能力;③,协商参数,通信双方共同确认通信中的一些必备参数数值。

两个比较重要的状态:

  • LISTEN:服务器进入的状态,端口绑定成功,服务器准备就绪,随时可以有客户端连上来。
  • ESTABLISHED:连接建立完成,可以随时进行数据通信。

(经典问题: 三次握手换两次或者四次可以吗?

回答:两次不行,两次对于通信双方的接收能力和发送能力没有验证完成。

四次可以,就是把中间那次交互拆开为两次,但是这样性能就不如三次了。)

  • 四次挥手,客户端可以先发起第一次请求,也可以是服务端发起第一次请求。当客户端代码中调用socket.close方法或者客户端进程结束就会触发四次挥手。

四次挥手中间的两次交互是否可以合并?

其实,中间的ACK是由内核控制的,而中间的FIN 是调用应用程序控制的close后才会被触发,它们不是同一时机,所以不能合并。但是,特殊情况下,TCP有个延迟应答机制(下面有讲),如果有这个机制的加持,那么这两次交互可以合并,不过这是少数情况。

(经典问题: TCP的断开连接,可以三次挥手完成吗?

回答:可以,但是这是少数情况,如上回答即可。)

两个比较重要的状态:

  • CLOSE_WAIT:被动一方进入的状态,等待应用程序调用close方法。

(经典问题: 服务器大量出现CLOSE_WAIT时怎么办?

回答:说明代码有大量bug,代码很有可能忘记调用close或者没有及时调用close了,需要检查close。)

  • TIME_WAIT:它的存在是为了应对最后一个ACK丢包的场景。该状态有一个规定的等待时间,一般是2 MSL(这个时间是理论上网络中两个节点之间传输数据的最大时间),超过该时间,就意味着最后一个ACK已经被对方接收,TIME_WAIT就会被释放。

(经典问题: 服务器大量出现TIME_WAIT时怎么办?

回答:说明服务器中存在大量主动断开TCP连接的操作,这个操作对于服务器来说,很有可能是不科学的,一般都是客户端主动断开连接。)

四、滑动窗口

TCP除了保证可靠传输之外,还需要尽可能高效的传输数据,滑动窗口就是一种提高传输效率的机制。如下:批量发送数据,将等待时间重叠。

 窗口大小指的是⽆需等待确认应答而可以继续发送数据的最大值。上图的窗口大小就是4000个字节 (四个段)。

发送前四个段的时候,不需要等待任何ACK,直接发送;收到第⼀个ACK后,滑动窗口向后移动,继续发送第五个段的数据;依次类推。

操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只 有确认应答过的数据,才能从缓冲区删掉;

 窗口越大,网络的吞吐率就越高。

但是,如果在滑动窗口中出现丢包怎么办?

  • 数据包已经抵达,ACK被丢了:

比如说,1001丢了,但是收到了2001,那就意味着1~1000已经收到了,然后发送了1001~2000,ACK又发送了2001,所以这种并不要紧,因为可以通过后续的ACK进⾏确认。

  • 数据包直接丢了:

当某⼀段报⽂段丢失之后,发送端会⼀直收到1001这样的ACK,就像是在提醒发送端"我想要的是 1001" ⼀样;

 如果发送端主机连续三次收到了同样⼀个"1001"这样的应答,就会将对应的数据1001-2000重新 发送;

这个时候接收端收到了1001之后,再次返回的ACK就是7001了,因为2001~7000接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中。这种机制被称为"高速重发控制"(也叫"快速重传")。

五、流量控制

接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等⼀系列连锁反应。因此TCP⽀持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做流量控制。

接收端将自己可以接收的缓冲区大小放入TCP首部中的"窗口大小"字段,通过ACK端通知发送端;  窗口大小字段越大,说明网络的吞吐量越高;接收端⼀旦发现自己的缓冲区快满了,就会将窗口大小设置成⼀个更小的值通知给发送端;发送端接受到这个窗口之后,就会减慢自己的发送速度;如果接收端缓冲区满了,就会将窗口置为0;这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。

TCP里的“16位窗口大小”就是存放了窗口大小信息。16位,也就是64kb,但窗口大小也不一定就是64kb,TCP⾸部40字节选项中还包含了⼀个窗口扩大因子M,实际窗口大小是窗口字段的值左移M位。

六、拥塞控制

该机制和流量控制类似,都是和滑动窗口搭配的机制。

在不清楚当前网络状态下,贸然发送大量的数据,可能引发问题。因此TCP引⼊慢启动机制,先发少量的数据,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据。

此处引⼊⼀个概念为拥塞窗口

 发送开始的时候,定义拥塞窗口大小为1,每次收到⼀个ACK应答,拥塞窗⼝加1。 每次发送数据包的时候,将拥塞窗口和接收端主机反馈窗口大小做比较,取较小的值作为实际发送的窗口。

"慢启动"只是指初使时窗口大小比较小,传输速度慢,它的增长速度非常快。

为了不增长的那么快,因此不能使拥塞窗口单纯的加倍,此处引⼊⼀个叫做慢启动的阈值。当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长。当TCP开始启动的时候,慢启动阈值等于窗口最大值。 在每次超时重发的时候,慢启动阈值会变成原来的⼀半,同时拥塞窗口置回1。

少量的丢包,仅仅是触发超时重传;⼤量的丢包,就认为是网络拥塞。

当TCP通信开始后,网络吞吐量会逐渐上升;随着网络发生拥堵,吞吐量会立刻下降。

拥塞控制,归根结底是TCP协议想尽可能快的把数据传输给对方,但是⼜要避免给网络造成太大压力的折中方案。

(注意:流量控制和拥塞控制都会产生一个窗口大小,选用较小的一个作为其窗口大小即可。)

七、延时应答

延时应答也就是ACK不会立即返回,而是等待一会再返回。其核心目的就是为了提升传输效率。

决定传输速度的关键因素,就是窗口大小,在能够承受的前提下,窗口大小越大越好,而延时应答可以提高窗口大小。

延时时间的确定有两种方式:

  • 按照一定时间来指定延时;
  • 按照收到的数据量。

实际上这个时间是两者结合来确定的。

八、捎带应答

捎带应答是建立在延时应答的基础上,以提升效率的机制。

日常开发中,客户端与服务器之间是“一问一答”的通信模型。

正常情况下,ACK是内核收到请求自动返回的,响应数据是应用程序代码执行一系列逻辑之后返回的。但是由于延时应答的存在,ACK不一定立即返回,在ACK稍等的过程中,正好返回响应数据,此时,在响应数据中,TCP中的ACK这一位置上,把确认序号/窗口大小都设置上。这种操作就叫捎带应答。 

九、面向字节流

在字节流读写数据的场景中,会涉及粘包问题。

假设有一个翻译服务器,客户端向服务器发送若干请求,由于字节流的特点,读的时候可以一次读一个字节,也可以一次读多个字节,此时服务器无法区分一个完整的单词的界限。这就会产生“粘包问题”。

其实,此处“粘”的是应用层的数据包,区分包之间的界限即可解决。那么有以下方法:

  • 分隔符:在包和包之间使用分隔符区分;
  • 约定包的长度:在包头约定一个包的长度。

粘包问题不仅仅是TCP的问题,读写文件也会涉及。

十、异常情况

异常情况有以下情况:

  • 其中某个进程崩溃或终止

进程结束会释放⽂件描述符,仍然可以发送FIN。和正常关闭没有什么区别。

  • 某个主机被关机(正常流程的关机)

对于这种情况,操作系统会先尝试强制结束所有的用户进程,然后再进入关机流程。这种情况与进程终止相同。

  • 某个主机电源掉电

假设A与B进行通信,A突然掉电,那么A就会无法做出反应,B却不知道。

如果B是发送数据方,B接下来发送的数据无法收到ACK,B就会触发超时重传,重传几次之后,会发送复位报文(RST),RST也没有响应,B就会单方面删除保存的A的信息。

如果B是接收方,那么当A暂停后,B无法确定A的情况,当B没有收到A的数据,一段时间后,B就会触发“心跳包”(心跳包可以认为是一个没有载荷的数据包,只是为了触发ACK),B给A发送一个心跳包,如果A正常,就会返回ACK,如果A没有回应,那就说明A “挂”了。连续发送若干次心跳包,如果A一直没有回应,那么B就会单方面释放连接。

(TCP虽然内置了心跳包,但是通过它发现问题的响应周期比较长,在实际开发中,经常会实现应用层的心跳包,实现更高频率,更短周期的响应。)

  • 网线断开

这种情况本质上就是第三种的情况。

假设A和B之间及案例TCP的连接,A和B之间的网线断开了。

如果A是发送方,B是接收方,从A来看,就会触发超时重传,触发RST,单方面删除信息;从B来看,就会触发心跳包,对方无响应,单方面删除信息。

标签:窗口,重传,ACK,应答,十个,TCP,发送,机制
From: https://blog.csdn.net/m0_60462557/article/details/140151410

相关文章

  • java使用Netty实现TCP收发消息的例子,多线程并且含断线自动重连
    需求:有一个TCP的服务,需要使用Netty开发一个TCP连接并收发消息的程序。要求多线程并且含断线自动重连能力。组织结构,使用JavaMaven编程方式功能还包含读取配置文件和log4j2写日志部分 完整代码:App.javapackagecom.LSpbxServer;importorg.slf4j.Logger;import......
  • 实现返利App中的数据缓存与预加载机制
    实现返利App中的数据缓存与预加载机制大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!数据缓存是指将经常访问的数据临时存储在高速存储器中,以提高数据访问速度和系统性能。在返利App中,数据缓存和预加载机制能......
  • Python实现基于先验MASK的视频问答(先验注意力机制的视频问答即之江数据集问答方案)
    !!!有需要的小伙伴可以通过文章末尾名片咨询我哦!!! ......
  • [计算机网络]TCP/IP
    OSI七层模型应用层表示层会话层传输层网络层数据链路层物理层TCP/IP四层模型应用层传输层网络层数据链路层物理层全双工全双工(Full-Duplex)是指在通信中,数据传输能够在两个方向上同时进行,允许双方在同一时间既能发送数据,又能接收数据。这种方式使得通信的双方可以实......
  • 禅道二次开发——禅道zentaoPHP框架扩展机制——对控制层扩展
    对现有模块的control层的扩展有两种,一种是覆盖现有的方法,一种是增加新的方法。下面我们来看下如何进行扩展。......
  • 防抖与节流机制
    防抖与节流:本质上是优化高频率执行代码的一种手段浏览器的resize、scroll、keypress、mousemove等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用防抖(debounce)和节流(throttle......
  • 客服系统回调机制,私信自动回复回调第三方,客服回复回调第三方
    演示网站gofly.v1kf.com针对私信自动回复的客户有一个需求,他对接的是认证的企业号。当用户进入他的私信绘画页发送消息后,他希望在自己的系统里获取这条消息,并把这条消息入库以及调用自己程序内部的AI进行处理。处理完成后,再将回复结果回复给用户。为了实现这一需求,需要在客服......
  • 简单课设:基于TCP协议的客户/服务器聊天室
            随着计算机的普及,网络编程也显得愈发重要,同时掌握实现客户/服务器程序的编写方法也不可忽视。通过学习,我们将了解TCP协议在网络通信中的重要性,掌握如何使用在Linux或Windows平台上编写简单的TCP客户/服务器程序。课程设计分为两个部分:服务器端和客户端。在服务......
  • 2025秋招计算机视觉面试题(七)-NMS详细工作机制及代码实现
    问题看到一句话:NMS都不懂,还做什么Detection!虎躯一震……懂是大概懂,但代码能写出来吗???在目标检测网络中,产生proposal后使用分类分支给出每个框的每类置信度,使用回归分支修正框的位置,最终会使用NMS方法去除同个类别当中IOU重叠度较高且scores即置信度较低的那些......
  • 深入理解Qt的隐式共享机制
    在Qt中,一个关键的性能优化特性是其数据结构的隐式共享机制,这在Qt的文档和API中常被称为“隐式共享”或“写时复制(Copy-On-Write,COW)”。本文将详细介绍这一机制,并通过QString类的实现代码和相应的反汇编代码来阐释其工作原理。隐式共享的定义和优点隐式共享是一种内存管......