传输层协议 ——— TCP协议

      最后更新:2022-06-11 22:49:22 手机定位技术交流文章

      文章目录

      • TCP协议
        • 谈谈可靠性
        • TCP协议格式
          • 序号与确认序号
          • 窗口大小
          • 六个标志位
        • 认可反应机制(ACK)
        • 超时重传机制
        • 连接管理机制
          • 三次握手
          • 四次挥手
        • 流量控制
        • 滑动窗口
        • 拥塞控制
        • 延迟应答
        • 捎带应答
        • 面向字节流
        • 粘包问题
        • TCP异常情况
        • TCP小结
        • 基于TCP的应用程序层协议

      TCP协议

      谈谈可靠性

      TCP被称为“传输控制协议”(Transmission Control Protocol),是当今互联网中最广泛使用的层协议。

      TCP协议被广泛使用,主要是因为它提供了详细的可靠性保证,并且因为有许多基于TCP的高级应用程序,例如HTTP、HTTPPS、FTP、SSH,甚至MySQL的TCP基础使用。

      为什么存在不可靠的网络?

      大多数现代计算机都基于冯·诺伊曼的建筑。
      在这里插入图片描述
      虽然输入、输出、内存和CPU都在这个机器上,这些硬件设备彼此独立。如果它们之间存在数据相互作用,你必须设法交流,这些设备实际上是通过电线连接的。连接内存与外部设备之间的“线”称为IO总线。内存与CPU之间的“线”称为系统总线。因为这些硬件设备都是在一个机器上,所以这里的数据传输的“线”很短,数据传输过程中出现错误的概率也是较低的。

      但是,如果要通信的设备距离千里之遥,设备之间的“线”会变得非常长,在传输数据时发生错误的概率会大大增加,必须引入可靠性,以确保数据被传输到相反的端子。

      简言之,网络缺乏可靠性的根本原因是,用于长距离数据传输的“线”太长,在长距离数据传输过程中可能存在各种问题,而TCP是在这方面诞生的,而TCP是一个可靠的协议。

      思维扩展:

      • 事实上,一个单一的计算机可以被看作是创建一个小网络,计算机上的各个硬件设备实际上是通信数据,而且它们在通信时也必须遵守自己的通信协议,但它们之间的通信协议更多地是描述某些数据的意义。

      为什么存在UDP协议?

      TCP协议是一种可靠的传输协议。使用TCP协议可以在一定程度上保证数据传输的可靠性。UDP协议是一种不可靠的传输协议。UDP协议的意义是什么?

      不可靠和可靠是两个中立词,它们都描述了协议的特征。

      • TCP协议是可靠的协议,这意味着TCP协议需要做更多的工作来确保数据传输的可靠性,而且越不可靠的因素出现,确保可靠性的成本(时间+空间)就越高。
      • 例如,在传输过程中的数据丢失、序列、检查和故障都是不可靠的情况。
      • 由于TCP必须解决不可靠的数据传输问题,它必须比UDP更加复杂,并且特别昂贵的维护。
      • UDP协议是不可靠的,这意味着UDP协议不需要考虑到数据传输时可能出现的问题,所以UDP足够简单使用和维护。
      • 应当指出,虽然TCP具有复杂性,但TCP效率不一定低于UDP。除了保证可靠性的机制外,还存在各种保证传输效率的机制。

      没有更好的UDP或TCP,只有谁最合适,TCP或UDP在网络通信中的具体使用完全取决于最高级应用程序场景。如果应用场景严格要求传输过程中的数据可靠性,然后必须使用TCP协议,如果应用程序场景允许数据传输发生少量损失,那么,一定要优先使用UDP协议,因为UDP协议足够简单。

      TCP协议格式

      TCP协议格式如下:
      在这里插入图片描述
      每个TCP头条的含义如下:

      • Source/Objective port number: 指示数据来自哪些进程,以及向相反端的服务器发送哪些进程。
      • 32位序列/32位确认序列:在TCP消息中每个字节的数据编号和彼此的确认是TCP可靠性保证的重要领域。
      • 四位TCP字节长度:表示由四位字节组成的TCP字节长度。
      • 6位预留字段:在TCP头条中暂时不使用的6位额外空间。
      • 16位窗体大小: 为保证TCP可靠性机制和提高效率机制的重要领域.
      • 16位元测试和:由发送器填充,使用CRC校正。 如果接收器检查不通过,接收的数据被认为是问题(检查并包括TCP第一+TCP数据部分)
      • 16位元紧急指针: 识别消息中紧急数据的极化,并需要与标记字段中的URG字段一致使用。
      • 选项字段: TCP头条允许您携带额外的选项字段,最大40字节。

      TCP头部的六个标记位置:

      • URG: 紧急针是否有效?
      • ACK: 确认序列号是有效的.
      • PSH: 提示接收程序立即读取TCP接收缓冲器中的数据.
      • RST:要求另一方重新建立连接。 我们称载有RST标识符的报告为多重报告段。
      • SYN:请求与另一方建立联系。 我们呼叫 messages carrying SYN identifiers synchronous message segments。
      • FIN:通知另一方端子关闭。我们将载有 FIN标识符的报告称为报告段末。

      TCP头条基本上是内核中的位类型,在将TCP头条装入数据时,事实上,一个变量是由位数类型定义的,然后在TCP头部填入属性字段,最后将该TCP头条复制到数据的第一个部分,在此之前,TCP头条已经被包装了。

      TCP如何将标题与有效负荷分开?

      当TCP从底部接收消息时,虽然TCP不知道标题的具体长度,但最初的20个字符是TCP的基本标题,这些20个字符覆盖了四个最高部门。

      因此,TCP与标题和有效负载有如此的区分:

      • 当TCP接收消息时,它首先读取消息的第一个20字节,并从中提取第一个四个部门,从而获得TCP标题的大小 s i z e size s i z e
      • 如果 s i z e size s i z e 如果值超过20字节,则需要继续从报告中阅读 s i z e − 20 size-20 s i z e 2 0 节点的数据, 数据的这个部分是TCP头部的选项字段.
      • 在读取基本的TCP消息和选项字段后, 其余的字段被加载.

      应当指出,TCP头部的四个第一个部长描述的基本单元是4字节,也是报告的宽度。 第一个部长的值范围为00~11,所以TCP头部的最大长度是 15 × 4 = 60 15times4=60 1 5 × 4 = 6 0 字节,因为基本头条长20字节,头条的选项字段长最大40字节。

      如果在TCP字段中没有选项字段,则TCP字段长20字节,在字段中的第一四个部长字段的值为 20 ÷ 4 = 5 20div4=5 2 0 ÷ 4 = 5 ,也就是0101。

      TCP如何决定哪些协议将有效负荷交付到顶层?

      应用程序层中的每个网络进程必须绑定一个端口数。

      • 服务端口进程必须显示绑定端口编号.
      • 客户端进程由系统动态地绑定到一个终端号码.

      TCP头条覆盖了目标端口号,因此TCP可以从头条中提取目标端口号,找到相应的应用程序层进程,然后将有效负荷转移到相应的应用程序层进程进行处理。

      注意,内核以 hashing 方式维护端口号和进程ID之间的映射关系,以便传输层能够通过端口号快速找到相应的进程ID,然后找到相应的应用程序层进程。

      序号与确认序号

      什么是真正的可靠?

      在进行网络通信时,一方发出的数据后,它 不能 保证 数据 将 以 相反 的 方式 获得 成功,因为数据在传输过程中会产生各种错误,只有从主机收到响应消息后,主机可以确保上次发送的数据得到可靠的另一端,这就是真正的可信性。
      在这里插入图片描述

      但是,TCP是保证双方通信的可靠性,虽然 Host A 现在 能够 确保 它 上次 发送 的 数据 由 Host B 得到 可靠,但主机B还需要确保它向主机A发送的响应数据被主机A可靠地接收。因此A主机收到B主机的响应消息后,还必须对答复数据作出反应,但还必须确保由主机发送的响应数据的可靠性。这使我们陷入一个死循环。
      在这里插入图片描述
      因为只有当一个端接收另一端的响应消息,它才能确保它上次发送的数据被另一端可靠地接收,但是当双方通信时,总是有最新的消息,因此不能保证100%的可靠性。

      严格地说,因特网通讯没有100%的可靠性,因为当双方沟通时,总是有一个最新的信息,不能回答。但实际上没有必要保证所有信息的可靠性,我们只需要确保双方发送的每一个核心数据都与相应的响应进行通信。对于一些不重要的数据(例如响应数据),我们不需要保证它的可靠性。因为计数器不接收这些响应数据,确定上次发送的邮件丢失,在此情况下,以前发送的数据可以重新传输到相反的端。
      在这里插入图片描述
      该策略在TCP中称为确认响应机制。 应当指出,确认响应机制并不保证双方之间的所有通信的可靠性,但只要一方收到另一方的响应信息,它表明它上次发送的数据被另一方可靠地接收。

      32位序号

      如果双方正在交流数据,只接收最后传输的数据的响应才能发送下一个数据,那么双方的通信过程是序列的,效率是可行的。

      因此,当双方在网络中通信,允许一个方向和另一个方向连续发送多个消息数据时,只需要确保每个发送的消息都具有相应的响应消息,在此情况下,也可以确保这些消息被另一方接收。
      在这里插入图片描述
      但是,在连续发送多个消息时,由于在网络传输过程中每个消息所选择的路径可能不同,因此,这些消息在相反的主机上到达的顺序可能与它们发送的顺序不同。但报告的顺序也是一种可靠性,因此,TCP头部的32位序列的功能之一就是确保消息的顺序。

      TCP编码了每个发送的数据, 称为序列数.

      • 例如,发送器现在发送3千字节的数据,如果发送器发送1千字节,则需要3个TCP消息发送3千字节的数据。
      • 在此情况下,三个TCP消息中的32位序列数是发送数据中的第一个字母的序列数,因此分别是001和2001。

      在这里插入图片描述
      此时接收器收到了三个TCP消息,您可以根据TCP头部的32位序列数重新排序三个消息(此操作发生在传输层中),重新排序并将其放在TCP的接收缓冲区,在此点,接收者发送的邮件的顺序与发送者发送的邮件的顺序相同。

      • 当接收器重载消息时,当前消息的32位序列可以根据当前消息中的字节数和其有效负载,然后确定下一个消息的相应序列。

      32位确认序号

      TCP消息中的32位确认序列告诉前端我收到的哪些数据以及下一次你的数据应该在哪里开始。

      以刚才的例子为例,当B主机接收A主机发送的32位序列数为1的讯息时,由于报告载有100字节的数据,因此,主机B接收了1-100字节的数据序列数目,然后,在主机B发送到主机A的响应数据的标题中32位确认序列的值将填入1001。

      • 一方面,它告诉主机A,在1001之前序列数已经收到。
      • 另一方面,它告诉主机A,下次它向我发送数据,它应该从序列号1001字节的数据开始发送。

      然后,当主机B响应其他发送给主机A的讯息时,32个发送给主机A的响应被填充以确认序列。
      在这里插入图片描述
      注意:

      • 响应数据和其他数据一样,也是完整的TCP消息,虽然消息可能没有有效负载,但至少有一个TCP头条。

      报文丢失怎么办?

      例如,主机A向主机B发送了三个消息,每个消息的有效负载为100字节,三个消息的32位序列数分别为1,001和2001。

      如果这些三个消息在网络传输过程中丢失,最后, 只有 有 序列 编号 1 和 2001 的 报告 由 东道主 B 收到,所以当主机B重新排序消息时,你会发现只有1-100和2001-300收到。此时主机B响应主机A,其响应标题中的32位确认序列为1001,告诉主机A,下次你给我发送数据时,你应该从序列号1001字节的数据开始发送。
      在这里插入图片描述
      注意:

      • 此时,当主机B响应主机A时,其32位确认序列不能填补3001,因为1001-200是3001之前,如果主机A直接响应3001,则序列数表示所有3001以前的字节数据已经收到。
      • 因此,主机B只能以1001响应主机A,当主机A接收确认序列时,确定序列为1001的消息被丢失,主机A可以选择重新传输数据。

      因此,发送者可以根据发送者发送的确认序列确定,是否在传输过程中可能丢失了消息。

      为什么使用两套序列数字机制?

      如果双方通过向一个端发送数据和向另一个端接收数据进行通信,则只需使用一系列序列。

      • 当发送器发送数据时,序列被处理为32位序列。
      • 当接收器响应发送器发送的数据时,该序列被认为是32位确认序列。

      但事实上,TCP并没有这样做,根本原因是因为TCP都是双重任务,他们可能都想同时发送信息。

      • 在 双方 发出 的 声明 中, 不仅 需要 填写 32 位 序列, 以 说明 他们 目前 发送 的 数据 的 序列 。
      • 你还需要填入32位确认序列来确认你以前向对方发送的数据,并告诉对方下一次该发送哪些字节序列。

      因此,当TCP通信进行时,双方需要有一个确认响应机制,如果一组序列号码不能满足要求,则在TCP消息中出现两组序列号码。

      总结一下:

      • 32位序列的功能是确保数据按顺序到达,并且这个序列也是在向相反端发送消息时填补32位确认序列的基础。
      • 32-bit认证序列的作用是告诉端到端当前接收的数据和从哪个序列开始下一次数据被发送到端到端。
      • 序列和确认序列是确认响应机制的数据化,确认响应机制由序列和确认序列保证。
      • 此外,可以通过序列和确认序列来确定消息是否丢失。

      窗口大小

      接收和发送TCP缓冲器

      TCP本身接收缓冲器和发送缓冲器:

      • 接收缓冲器用于暂时存储接收数据。
      • 发送缓冲器以暂时保存未发送的数据。
      • 两个缓冲区都是在TCP传输层内实现的.

      在这里插入图片描述

      • TCP在缓冲区发送的数据被写入上层应用程序层。 当系统调用接口如上层调用写/发送实际上没有直接发送数据到网络时,它将应用程序层的数据复制到TCP发送缓冲层。
      • TCP在缓冲区接收数据,最终由应用程序层读取。 当上部调用系统调用接口(如 read/recv)时,数据实际上不是直接从网络读取,而是从TCP的接收缓冲区复制到应用程序层。
      • 就像调用读写来读写文件一样,它不是直接从磁盘读取数据或者直接写入磁盘的文件缓冲器的读写操作。

      在这里插入图片描述
      当数据被写入TCP的发送缓冲器时,可以返回相应的写入/发送函数,实际上是TCP决定数据什么时候和如何在发送缓冲器中发送。

      我们称TCP为传输层控制协议,由于最终数据的发送和接收方式,以及如何解决在传输数据时遇到的问题,所有都是由TCP本身决定的,用户只是复制数据到TCP发送缓冲区,您也可以从TCP接收缓冲区读取数据。
      在这里插入图片描述
      注意,两个通信的TCP层是相同的,因此两个通信的TCP层都是发送和接收缓冲。

      TCP中发送和接收缓冲器的意义

      发送和接收缓冲器的功能:

      • 当数据通过网络传输时,可能会发生一些错误,在此情况下,可以要求发送者重新传输数据,因此,TCP必须提供发送缓冲器以暂时存储发送的数据,避免需要重新传输数据。只有在传送数据得到可靠的另一方时,在缓冲区发送的数据的这一部分只能被覆盖。
      • 接收器处理数据的速度有限,为了 确保 不能 处理 的 数据 不会 被 强迫 丢弃,因此,TCP必须提供接收缓冲器以暂时存储未处理的数据,因为数据传输很昂贵,我们不能随心所欲放弃正确的报告.此外,在接收缓冲区也进行TCP数据检索.

      经典的生产者消费者模式:

      • 为发送缓冲器,顶层应用程序不断将数据插入缓冲器发送,网络的下层继续从发送缓冲区提取数据,以便进一步密封。在此阶段,高级应用发挥了生产者的作用,网络的底层扮演着消费者的角色,发送的相应的缓冲区是“贸易站”。
      • 对于接收缓冲区,顶层应用程序不断处理接收缓冲区的数据,网络下层继续将数据插入接收缓冲区。当前,高级应用的任务是消费者的任务,网络的底层扮演了生产者的角色,接收缓冲区 corresponds to the "trade place".
      • 因此,发送缓冲和接收缓冲的引入等同于两个生产者-消费者模型的引入,生产者-消费者模型将上层应用与下层通信细节结合起来,生产者-消费者模型的引入也支持同时和忙碌不平等。

      窗口大小

      当发送器向相反端发送数据时,必须在缓冲器中发送您的数据到相反端的接收缓冲器。但缓冲区很大,如果接收器处理数据的速度比发送器发送数据小,因此,接收器的接收缓冲区总是有时间被填满,然后发送器将数据发送回,造成数据丢失,这导致一系列链路反应,如丢失数据包的重新传输。

      因此,TCP头部有一个16位窗格大小,这个16位窗格大小是填充在自接收缓冲区剩余空间的大小,即当前主机接收数据的能力。

      当接收器响应发送器发送的数据时,它可以根据当前接收的缓冲区剩余空间的16位窗口大小通知发送器,并且发送器可以根据窗口大小字段调整发送数据的速度。

      • 视窗大小越大,接收器接收数据的能力就越强,发送器发送数据就越快。
      • 视窗大小越小,接收器接收数据的能力就越弱,发送器可以降低数据的速度。
      • 如果窗口大小值为0,则表示接收器已填满接收缓冲区,接收器不再发送数据。

      理解现象:

      • 在编写TCP接口时,我们叫 read/recv函数读取从接口的数据,因为接口中没有数据可能被封锁,基本上因为没有数据在TCP接收缓冲器中,我们实际上在接收缓冲器中被封锁。
      • 当我们调用写/发送函数写数据到插座时,它可能被封锁,因为插座已经满了,基本上因为TCP发送缓冲已经满了,而我们实际上在发送缓冲中封锁它。
      • 在生产者-消费者模型中,如果生产者生产数据被封锁,或者消费者消费数据被封锁,则必须被封锁,因为某些条件不具备。

      六个标志位

      为什么有标志的地方?

      • 有多种类型的TCP通知,包括在正常通信中发送的正常通知、在连接建立通知期间发送的请求和在脱离通知期间发送的分离通知。
      • 在收到不同类型的报告时,必须完善相应的行动,例如,正常通信信息需要放在接收缓冲区等待上层应用程序读取,并且创建和切断连接的讯息的内容不由用户处理。相反,操作系统需要在TCP层上执行相应的握手和哨声。
      • 也就是说,不同类型的报告符合不同的处理逻辑,所以我们需要能够区分不同类型的报告。 TCP被用来区分标题中的六个标记字段,每个字段只占一小块空间,代表错误为0和真为1。

      SYN

      • 该消息中的SYN设置为1,表明该消息是一个基于连接的请求消息。
      • SYN仅在连接建立阶段设置,在正常通信中不设置。

      ACK

      • 该消息中的ACK设置为1,表明该消息可以为收到的消息确认。
      • 一般而言,除了第一个请求消息没有设置ACK,其余消息基本上设置ACK,因为发送的数据本身对发送给另一方的数据具有一定的验证能力,因此当发送数据时,双方都能够响应向另一方发送的数据。

      FIN

      • 该消息中的 FIN 设置为 1, 表明该消息是连接不连接的请求消息。
      • 端数仅在断开阶段设置,在正常通信中不设置。

      URG

      当双方在网络中沟通时,因为TCP确保数据按顺序到达,即使发送器将发送的数据分成几个发送的TCP消息,这些数据在最终到达接收端时也被订购,因为TCP可以按序列重新排序这些TCP消息,最后,可以确保数据到达相反端的接收缓冲区。

      TCP的有序访问本身也是我们的目标,在这个点上,顶层也必须从接收缓冲区读取数据。 但有时发送器可能发送一些需要从另一方顶层提取的“紧急数据”。
      在这里插入图片描述
      这需要使用URG标记位和TCP头部的16位紧急指针。

      • 当URG标记位置设置为1时,必须通过TCP头部的16位紧急指针找到紧急数据,否则通常不需要查看TCP头部的16位紧急指针。
      • 16位特急指针代表报告中的特急数据的极化。
      • 由于只有一个紧急提示符,它只能在数据节中识别一个位置,因此紧急数据只能发送一个单词,而这个单词的具体含义在这里没有讨论。

      recv函数的第四个参数旗有一个叫做MSG_OOB的选项要设置,OOB是带外数据的缩写。外部数据是最重要的数据之一,因此,如果高级人员想阅读紧急数据,可以使用 therecv函数读取,然后设置MSG_OOB选项。
      在这里插入图片描述
      与之对应的send函数的第四个参数flags也提供了一个叫做MSG_OOB的选项,上层如果想发送紧急数据,就可以使用send函数进行写入,然后设置MSG_OOB选项。
      在这里插入图片描述

      PSH

      消息中的PSH设置为1,这告诉对方尽快将收到的缓冲区的数据送到上层。

      我们一般认为:

      • 当使用 read/recv来读取缓冲器的数据时,如果缓冲器中有一个数据读取/恢复函数,则数据可以读取并返回,如果缓冲区没有数据,然后读取/恢复函数在此点被封锁,直到缓冲区内有数据才读取和返回数据。

      事实上,这个说法并不准确,事实上,接收缓冲区和发送缓冲区都有水位线的概念。
      在这里插入图片描述

      • 例如,如果我们假设TCP接收缓冲器为100字节,则读取/恢复函数只在接收缓冲器中有100字节时读取和返回数据。
      • 如果接收缓冲区有数据,读取/恢复函数读取和返回数据,读取/恢复函数经常读取和返回数据,从而影响读取数据的效率(切换内核和用户模式也是昂贵的)。
      • 因此,当读取/恢复函数被调用时,接收缓冲器不是读取/恢复,而是当缓冲器中的数据量达到一定数量时。

      当消息中的PSH设置为1时,它实际上告诉对方的操作系统,尽快将缓冲区接收的数据送到上层,尽管缓冲区接收的数据尚未到达指定的水线。这就是为什么我们使用读取/读取函数读取数据的原因,预期读取的字节数和实际读取的字节数不一定一致。

      RST

      • 消息中的RTT设置为1,表明另一方需要重新建立连接。
      • 如果通信没有很好地建立,则将数据发送到另一方,另一方发送的响应消息中的RST信号位置设置为1,表明另一方要求重新建立连接。
      • 当两个当事人之间正常通信的良好连接建立时,如果在通信中发现连接之前出现异常,连接将重新建立。

      认可反应机制(ACK)

      TCP保证可靠性的机制之一是确认响应机制。

      确认响应机制来自TCP头条,32位序列和32位确认序列是保证的。需要再次强调的是,确认反应机制并不保证双方之间所有通信的可靠性。相反, 收到 对方 的 答复,确保您向另一方发送的信息得到可靠。
      在这里插入图片描述

      如何理解每个节点的所有数据的TCP编码?

      TCP是面向旁通的,所以我们可以把TCP的发送缓冲和接收缓冲都想象成一个字串阵列。
      在这里插入图片描述

      • 此时,上层的每个字节数据在复制到TCP发送缓冲区时,自然有序列,序列是字符集的子集,只是子集不是从0开始的,而是从1开始的。
      • 当双方通信时,本质是将它们在缓冲区内发送的数据复制到对方的接收缓冲区。
      • 发送者在数据时间标题中输入的序列实际上是发送的数据字节的数目,第一个数据字节与发送缓冲区的标记相符。
      • 当接收器接收到数据的响应时,响应头部的确认序列实际上是接收缓冲区最近接收的有效数据的下一个位置的相应的子符号。
      • 当发送者接收接收者的响应时,可以继续从下面标记的位置发送确认序列。

      超时重传机制

      当双方通过网络通信时,发送者在特定事件间隔内发送数据给另一方,如果另一方没有收到响应,发送者则重新发送数据,这是TCP的超时再传输机制。

      应当指出,TCP保证了两种通信的可靠性,部分体现在TCP协议头条中,部分体现在TCP代码逻辑的实现中。

      例如,超时再传输机制实际上意味着发送者在发送数据后打开一个计时器。如在该期间未收到发送的资料的确认,则应对该消息作出回应,报告 将 再 转发,通过TCP代码逻辑实现,它没有反映在TCP头条。

      丢包的两种情况

      丢失分为两个情况,其中一个是发送数据消息丢失,发送者在一定时间内未能接收相应的响应消息,并且有超时再传输。
      在这里插入图片描述
      另一个损失的例子不是发送者发送的数据丢失,而是其他发送者发送的响应消息丢失。此时,发送者将重新发送超时,因为相应的响应消息没有收到。
      在这里插入图片描述

      • 当一个数据包丢失时,发送者无法区分发送的数据消息是否丢失或另一方发送的响应消息,因为在这两个情况下,发送者不能接收另一方发送的响应消息,并且发送者只能在时间上重发它。
      • 如果对方的响应消息丢失,导致发送者在一段时间内重发消息,接收者将再次收到重复消息数据,但不需要担心,接收者可以根据头条的32位序列判断消息是否收到,从而达到重发消息的目的。
      • 需要注意的是,当缓冲器中的数据被发送出去时,操作系统不会立即删除或覆盖发送缓冲区的数据,然后把它留在发送缓冲区,为了避免加班的传输,直至收到有关资料的答复,在缓冲区发送的数据的这一部分可以删除或覆盖。

      超时重传的等待时间

      超时再传输时间不能设置太长或太短。

      • 超时再传输时间设置太长,导致另一方在损失后长时间没有收到相应的数据,从而影响了整个再传输的效率。
      • 超时再传输时间设置太短,导致对方接收大量重复消息,可能对方发送的响应消息仍然在网络中传输,没有丢失数据包,但此时发送者开始再传输数据,发送大量重复消息也是浪费网络资源。

      因此,超时传输的时间必须合理,理想的情况是找到最少的时间,保证确认应在这段时间内返回。但这个时间的长短,它与网络环境有关。当网络良好时,再传输时间可以设置为更短的点,网络卡的再传输时间可以设置为稍长一点,换句话说,超时继电器设置的等待时间必须上下浮动,因此,这次不能是固定值。

      TCP 动态计算最大加班期,以确保在任何环境中都能实现高性能通信。

      • 在Linux(如BSD Unix和Windows)中,超时由500ms的单位控制,每次超时复发的超时时间是500ms的整数。
      • 如果重新输入后未收到答复,则下一回输入的等待时间为 2 × 500 2times500 2 × 5 0 0 ms。
      • 如果你仍未得到答复,下一次你被送回是 4 × 500 4times500 4 × 5 0 0 这样,它以指数的形式增加。
      • 当一个特定数量的重新传输被累积时,TCP认为网络或端口主机有异常,然后迫使连接关闭。

      连接管理机制

      TCP是面向连接的

      TCP的各个可靠性机制实际上不是从主机到主机,而是基于连接的,与连接是强相关的。例如,在服务器启动后,可能有多个客户端访问它。如果TCP不基于连接,这意味着服务器端只有一个接收缓冲,此时,每个客户端发送的数据将被复制到这个接收缓冲区,此时,这些数据可能相互干涉。

      并且我们需要在进行TCP通信之前建立一个连接,因为TCP可靠性保证是基于连接的,确保数据传输的可靠性的前提是首先建立一个好的连接。

      操作系统管理连接

      面向连接(Connectivity-oriented)是一种 TCP可靠性,只有在通信中建立良好的连接时才能保证,而且在机器上可能存在大量连接时,操作系统必须管理这些连接。

      • 当管理这些连接时,操作系统需要“首先描述,再组织”,在操作系统中必须有一个描述连接的结构,结构包含各种属性字段,用于连接,所有定义的连接结构最终被组织成某种数据结构,此时操作系统管理连接就变成了对该数据结构的增删查改。
      • 建立连接实际上是使用结构来定义操作系统中的结构变量,然后填入连接的各种属性字段,然后将其插入管理连接的数据结构。
      • 切断连接实际上是从管理连接的数据结构中删除连接,并释放连接所占用的资源。
      • 因此,连接管理也是昂贵的,这是管理连接结构的时间成本和存储连接结构的空间成本。

      三次握手

      三次握手的过程

      双方需要在TCP通信之前建立联系,我们称之为三手握手的过程。
      在这里插入图片描述
      例如,当客户端想与服务器通信时,它首先需要与服务器建立连接,由客户端作为发起者首先向服务器发送建立连接请求,然后两个底部的TCP自动握手三次。

      • 第一个握手: 客户端发送到服务器的SYN位数设置为1,表示要与服务器建立连接的请求。
      • 第二次握手:当服务器收到发送给客户端的连接请求消息后,它立即启动给客户端的连接创建请求并响应发送给客户端的连接请求,此时SYN和ACK比特在发送给客户端的信息中设置为1。
      • 第三个握手:客户端接收服务器发送的消息,并知道服务器已经收到自己发送的连接建立请求,并要求与自己创建连接。然后客户端响应服务器发送的消息。

      需要注意的是,客户端向服务器发起连接建立请求,是建立客户端与服务器方向的通信连接的请求,TCP是完全双重通信,因此,当服务器收到客户端建立连接的请求后,服务器也需要向客户端发起连接创建请求,要求建立从服务器到客户端方法的通信连接。

      为什么是三次握手?

      首先我们需要知道,连接建设没有100%成功,当沟通双方握手三次时,第一手可以保证对方会接受,因为第一两只手对第二只手有相应的反应,但第三次握手却没有相应的回应信息,如果客户端发送的ACK消息在第三次握手期间丢失,然后连接的创建将失败。
      在这里插入图片描述
      尽管客户端发起第三个握手并完成第三个握手,但服务器不会收到客户端发送的第三个握手,此时服务器无法建立相应的连接,因此,无论在建立连接时使用几个握手,最后的握手的可靠性都无法保证。

      由于建立一个接口不是100%成功,所以建立一个接口是基于几个握手的具体使用,实际上是看到更多的几个握手的优点。

      三手是验证双方间通讯渠道的最低数次:

      • 由于TCP是完全双重通信,连接的核心要求是验证双方的通信通道是否连接。
      • 三手是验证双方间通信通道的最小数次,三手之后,双方都可以知道他们和对方是否可以正常发送和接收数据。
      • 在客户端看来,当它收到服务器的第二次握手时,解释说你的第一手是被对方可靠地接受的,证明你能够从服务器上发送和接收,同时,当你收到服务器的第二次握手时,它也证明了服务器可以自己发送和接收,这证明了您和服务器都能生成和接收数据。
      • 在服务器看来,当它从客户手中得到第一手,证明客户可以发送和接收,当它收到了客户第三次握手时,说明你所给予的第二手被另一人可靠地接受了,它也证明了你可以发送和接收客户,在这一点上,它证明了你和客户都能发送和接收。
      • 由于三个握手可以验证两个通信通道的正常性,那么当然可以验证三个或更多的握手,但是由于三个握手已经验证了,所以不需要进行更多的握手。

      当连接建立时,三个手可以确保例外连接挂在客户端上:

      • 当客户端从服务器接收第二次握手时,客户端已经证明了两个通信渠道是连接的,所以当客户端发送第三次握手时,连接已经在客户端中建立。
      • 只有当服务器收到客户端的第三次握手时,服务器才会知道两个通信通道是连接的,在该点,相应的连接在服务器端建立。
      • 因此,当两方握手三次建立连接时,两方建立连接的时间不同。 如果客户最后一次握手失效,服务器端不会创建相应的连接,客户需要暂时保持异常连接。
      • 维护连接耗费时间和空间,因此第三方手势具有确保连接创建异常时,异常连接挂在客户端上而不影响服务器的优点。
      • 尽管客户端需要暂时维持这个异常,但客户端的异常连接并不非常大,与服务器不同,在多个客户端无法建立连接时,需要大量资源来维持这些异常连接。
      • 此外,未能建立的异常连接将不会维持.如果服务器长期没有收到客户端的第三方,第二手将随着时间的推移,此时, 客户有机会重新建立第三个震动.或者当客户端认为连接已经建立并向服务器发送数据时,此时,服务器发现与客户端没有建立连接,并要求客户端重新建立连接。

      因此,在建立连接时使用三个手有两个理由:

      • 三个握手是验证双方之间的通信渠道的最小数次,允许尽可能快地建立联系。
      • 三个握手可以确保在连接建立时的例外连接安装在客户端上(风险转移)。

      三次握手时手态的变化

      在这里插入图片描述
      三次握手时手态的变化如下:

      • 客户端和服务器在一开始就关闭了。
      • 为了服务器接收客户端的连接请求,必须将CLOSED状态转换为 LISTEN状态。
      • 此时,客户端可以向服务器发起三个握手,当客户端启动第一个握手时,状态被更改为SYN_SENT。
      • 在收到客户端的连接请求后,LISTEN状态的服务器将连接插入内核等待队列,并开始向客户端第二次握手,此时服务器状态被更改为SYN_RCVD。
      • 当客户端收到服务器发送的第二个握手时,它立即向服务器发送最后的握手,此时客户端的连接已经建立,并且状态已经建立。
      • 当服务器从客户端接收最后一个手时,连接成功地建立,服务器的状态就会建立。

      在三个握手的结束时,通信的两边都可以开始与数据进行交互。

      弦与三手的关系

      • 在客户端启动连接建立请求之前,服务器需要先输入LISTEN状态,在该阶段,服务器需要调用相应的听力函数。
      • 当服务器进入LISTEN状态时,客户端可以向服务器发起三个握手,这时客户端的相应呼叫是连接函数。
      • 注意,连接函数不参与底部三个握手,连接函数的函数只启动三个握手。 当连接函数返回时,底部 either successfully completed the three-handed connection or the bottom has failed the three-handed connection。
      • 如果服务器端 successfully completes the three handshakes with the client, a connection will be established at the server end, but this connection is in the waiting queue in the kernel, and the server end needs to obtain this established connection by calling the accept function.
      • 当服务器最终有一个良好的连接时,双方可以通过调用读取/恢复函数和写入/发送函数来与数据进行交互。

      四次挥手

      四次挥手的过程

      当双方终止TCP通信时,他们需要切断连接,切断连接的过程我们称之为四向波。
      在这里插入图片描述
      或者以服务器和客户端为例,当客户端和服务器通信完成时,需要脱离服务器,然后需要做四个波。

      • 第一个波:客户端发送到服务器的 FIN 位数设置为 1, 表示请求从服务器中切断.
      • 第二波: 服务器响应客户端调停连接的要求.
      • 第三波:当服务器收到从客户端切断请求时,没有数据发送给客户端时,服务器开始向客户端切断请求。
      • 第四波: 客户端响应服务器要求切断连接.

      四波之后,双方之间的联系被认为是真正断绝的。

      为什么是四次挥手?

      • 因为TCP是全职的,建立联系时,必须建立双方之间的联系。当连接被切断时,同样的情况也是如此。在切断连接时,不仅需要切断客户端与服务器的通信通道,同时将通信通道从服务器到客户端切断,每两波都表示在一个方向关闭通信通道。因此,在切断连接时需要四次振动。
      • 需要注意的是,四波中的第二波和第三波不能结合.因为第三手是发送给客户端的请求,当服务器端想要脱离客户端时,当服务器收到客户端的切断请求并作出响应时,服务器不确定是否立即启动第三波,因为服务器可能也有一些数据发送给客户端,向客户端的第三波仅在服务器端发送数据后才启动。

      四波状态的变化

      在这里插入图片描述
      四波状态的变化如下:

      • 在挥手之前,客户端和服务器在建立连接后处于STABLISHED状态。
      • 客户端向服务器发起连接切断请求,以便从服务器中切断,此时客户端的状态变为 FIN_WAIT_1。
      • 服务器响应客户端要求切断连接,服务器的状态被更改为CLOSE_WAIT。
      • 当服务器没有发送给客户端的数据时,服务器启动向客户端的切断请求并等待最后的ACK到达,此时服务器的状态变成了LSE_ACK。
      • 当客户端收到服务器的第三波后,它将最后的响应消息发送给服务器,这时客户端进入 TIME_WAIT状态。
      • 当服务器收到客户端发送的最后响应消息时,服务器将完全关闭连接并关闭。
      • 客户端等待2MSL(最大段寿命)进入CLOSED状态。

      在四波结束时, 通讯被成功切断.

      弦词与四首哨声之间的关系

      • 客户端启动了切断请求,该请求与客户端对关闭函数的主动调用相符。
      • 服务器启动了切断请求,该请求与服务器主动调用关闭函数相符。
      • 一个近似两个波, 两者都叫近似, 因此是四个波.

      CLOSE_WAIT

      • 当两边波动四次时,只要客户端调用关闭函数,而服务器不调用关闭函数,服务器输入CLOSE_WAIT状态,而客户端输入 FIN_WAIT_2状态。
      • 但只有在四个波之后,连接才真正断开。此时, 双方将释放相应的连接资源.如果服务器不主动关闭不必要的文件描述符,在CLOSE_WAIT状态下,服务器端将有大量的连接,每个连接占有服务器的资源,这最终导致服务器可用的资源越来越少。
      • 因此,如果不需要的文件描述符没有及时关闭,它可能导致连接资源不完全释放,除了导致文件描述符泄漏,这也是一个内存泄漏。
      • 因此,在编译网络接口代码时,如果在CLOSE_WAIT状态中在服务器端找到大量连接,您可以检查服务器是否没有提示关闭函数关闭相应的文件描述符。

      TIME_WAIT

      把手摇四次,然后摇三次,使袋子丢失:

      • 第一个包装波:客户端不接收服务器的响应,然后超时再传输。
      • 第二手丢失: 客户端无法接收服务器的响应,然后超时再发送.
      • 第三方损失:服务器无法接收客户端的响应,然后超时再发送。
      • 第四波切断:服务器无法接收客户端的响应,然后超时再传输。

      如果客户端在第四波后立即进入CLOSED状态,服务器没有收到客户端的响应,尽管有超时继电器,因为客户端关闭了连接。
      在这里插入图片描述
      服务器在多个超时继电器后不会收到响应,最终将关闭相应的连接,但需要在服务器连续的超时继电器中保持这个过时的连接,这是对服务器非常不友好的。

      为了避免这种情况,客户端在四个波之后不立即进入CLOSED状态,而是等待到它进入 TIME_WAIT状态,如果第四波消息丢失,客户端可以接收服务器的重复消息,然后响应。

      TIME_WAIT状态的必要性:

      • 客户端在四个波之后进入 TIME_WAIT状态,如果第四波丢失,客户端仍然能够接收服务器的重复 FIN消息并响应它一段时间,并且更有可能确保服务器收到最后的ACK。
      • 在客户端的最后波浪中,两方之间的历史通信数据可能没有被发送给另一方。 因此,客户端在四次波浪后进入 TIME_WAIT状态,并且可以确保两个通信渠道的数据尽可能在网络中散布。

      第四次挥手后,网络两边的状况可能有问题,虽然客户端尚未关闭连接,也未能接收服务器重复的连接切断请求,客户端 TIME_WAIT等最终将关闭连接,服务器在重复过时传输后也关闭连接。这种情况还允许服务器维护一个闲置连接,但毕竟是少数,TIME_WAIT状态的引入旨在确保由发起四向波的客户维持成本。

      因此,TCP不能充分保证建立和切断连接的可靠性,TCP保证建立和切断连接后双方之间的数据通信的可靠性。

      TIME_WAIT的等待时间是什么?

      TIME_WAIT的等待时间不是太长,也不是太短。

      • 太长允许服务员保持更长的时间 TIME_WAIT状态,在此期间服务员也需要花费费用维持连接,这是浪费资源。
      • 太短可能不能达到我们原来的目标,没有保证ACK会被另一方接受的可能性更大,没有保证数据会散布在网络中,此时 TIME_WAIT的含义也不再存在。

      TCP协议指定主动关闭连接的一方必须在四次摇摆后进入 TIME_WAIT状态,并在进入CLOSED状态之前等待两个MSL(最大分段寿命)。

      MSL在RFC1122中被指定为两个分钟,但实现情况在各个操作系统之间不同,例如, Centos7的默认配置值为60s。cat /proc/sys/net/ipv4/tcp_fin_timeout命令查看MSL的值。
      在这里插入图片描述
      TIME_WAIT等待时间设置为两个MSL原因:

      • MSL是TCP消息的最大寿命,因此如果2MSL的 TIME_WAIT状态持续,可以保证在两个传输方向中没有收到或延迟的消息段已经消失。
      • 同时, 从 理论 上 保证, 最后 报告 将 在 可靠 的 时候 提出 。

      流量控制

      TCP支持接收机确定发送器发送数据的速度的能力,一种叫做流量控制的机制。

      接收器处理数据的速度有限,如果发送端发的太快,导致接收端的缓冲区被打满,此时发送端继续发送数据,就会造成丢包,进而引起丢包重传等一系列连锁反应。

      因此,接收器可以通知发送器接收数据的能力,允许发送器控制发送数据的速度。

      • 接收器将可以接收的缓冲大小插入TCP顶部的“窗口大小”字段,并通过ACK通知发送者。
      • 视窗大小越大,网络的吞吐量就越高。
      • 一旦接收机发现其缓冲区快满了,它将窗口大小设置为一个较小的值通知给接收机。
      • 当发送器接收到这个窗口后,它会减慢自己的传输。
      • 如果接收器缓冲区满,则窗口值设置为0,发送者不再发送数据,而是需要定期发送窗口检测数据段,让接收者告诉发送者窗口的大小。

      当传送器得知接收器接收数据的能力为零时,传送器停止发送数据,此时传送器会知道什么时候继续发送数据。

      • 在接收器缓冲器中读取数据后,接收器将发送给发送者一个TCP消息,通知发送者其自己的窗口大小,发送者可以在接收器缓冲器有空时继续发送数据。
      • 问问自己。 发送器从时到时向接收机发送消息,它不载有有效的数据,只是问发送器关于窗口的大小,直到接收机缓冲区有空间,发送器可以继续发送数据。

      16是65535的最大数目. TCP窗口的最大数目是65535吗?

      在理论上,这是正确的,但事实上,TCP头部的40字节选项字段包含窗口扩展因子M,并且实际的窗口大小是从窗口字段左移的M值得到的。

      当我第一次向另一方发送数据时,如何知道窗口的大小?

      双方必须在TCP通信前三次握手,除了验证两边通讯通道是否平滑,两边还握手。还 交换 了 其他 资料,这包括通知对方是否能够接受,因此,双方在正式沟通之前都知道对方接收数据的能力。因此,双方在发送数据时没有缓冲溢出的问题。

      滑动窗口

      连续发送多个数据

      当TCP通信时,双方可以同时发送多个数据,从而重叠等待多个响应的时间,从而提高数据通信的效率。
      在这里插入图片描述
      应该指出,当双方进行TCP通信时,虽然双方可以同时发送大量信息,但它们不能把它们在缓冲区中发送的所有数据包起来发送到相反的端。

      滑动窗口

      发送者可以同时向另一方发送多个信息,这意味着发送的大量信息暂时没有答案。

      事实上,在缓冲区发送的数据可以分成三个部分:

      • ACK 数据 已 发送 和 收到 。
      • ACK数据已发送但未收到。
      • 还没有发送的数据。

      这里发送的缓冲器的第二部分叫做滑动窗口(有些人把三部分称为滑动窗口,而其他人则把第二部分称为窗口大小)。
      在这里插入图片描述
      滑动窗口说明发送者不需要等待ACK发送的最大数据量一次。
      在这里插入图片描述
      滑动窗口的最大意义在于它可以提高发送数据的效率:

      • 滑动窗口的大小与另一个窗口的大小和自拥窗口的较小值相同,因为发送数据时不仅考虑另一个窗口的接收能力,而且考虑当前的网络状况。
      • 这里我们不考虑拥挤的窗口,而是假设对方的窗口大小为400,所以发送者不需要等待ACK发送400字节的数据,所以滑动的窗口大小为400字节。
      • 在连续发送1001-200、2001-300、3001-400、4001-500段时,不需要等待任何ACK直接发送。
      • 在收到答辩人的答复时,确认编号是2001年注意 到 另 一 方 已 收到 数据 第1001 - 200 款,在此点,数据段应列入发送缓冲区的第一个部分,既然我们假设对方的窗户尺寸总是400,这样滑动的窗口现在可以向右移动,继续发送5001-600个数据段,以此类推。
      • 越大 sliding window, 网络的吞吐量越高, 也表明对方的接收能力越强.

      当发送器发送数据段并连续接收相应的ACK时,从ACK接收的数据段可以分配到滑动窗口的左边,而当前滑动窗口的大小决定了滑动窗口右边的数据是否应该分配到滑动窗口。

      TCP的重新传输机制要求暂时存储发送但未得到确认的数据,数据的这个部分实际上是滑动的窗口,只可覆盖或删除滑动窗口左侧的数据,因为这部分数据由另一方可靠地发送和接收,因此,除了限制直接发送数据而不接收ACK的能力之外, sliding window还有 sliding window也可以支持TCP重传输机制.

      整个滑动窗口会向右移动 吗?

      滑动的窗口不一定是一直向右移动的,以刚才的例子为例,假设对方收到1001-200数据段并答复,但上层的另一方并没有从接收缓冲区读取数据,此时,当答复人收到1001-200数据段时,另一扇窗的尺寸由400改为300。

      当发件人收到2001年收件人的答复编号时,1001-200数据段将分配到滑动窗口的左边,但此时,由于对方能接收300人,当1001-200数据段放在滑动窗口的左边时, sliding window的尺寸只有3,00个,因此,滑动窗口的

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/27133.html

          热门文章

          文章分类