通信网络/TCP 和 UDP 协议
TCP 和 UDP 协议是两种不同的协议,它们处理 IP 网络(互联网)中终端之间的数据通信。本页将讨论什么是 TCP 和 UDP,以及它们之间的区别。
在 OSI 模型中,TCP 和 UDP 是“传输层”协议。其中 TCP 是面向连接的协议,UDP 是无连接的协议。
在经历了模型的各个层级后,现在是时候看看 TCP 协议并研究其功能了。本节将帮助读者了解 TCP 的概念和特性,然后逐步深入 TCP 的细节,如连接建立/关闭、TCP 中的通信以及为什么 TCP 协议被称为可靠且自适应的协议。本节将以 UDP 和 TCP 的比较结束,并附上一个很好的练习,鼓励读者解决更多问题。
在撰写本节之前,信息已从各种来源学习,例如 TCP 指南、RFC、坦南鲍姆书籍和课堂笔记。
什么是 TCP?
理论上,传输层协议可以是一个非常简单的软件例程,但 TCP 协议不能被称为简单。为什么要使用像 TCP 一样复杂的传输层?最重要的原因取决于 IP 的不可靠性。事实上,TCP 下面的所有层都是不可靠的,并且逐跳传送数据报。IP 层逐跳传送数据报,并不保证数据报的传送;它是一个无连接的系统。IP 只处理数据报的路由;如果出现问题,IP 会毫不犹豫地丢弃数据包,并在过程中生成一条错误消息返回给发送方。确定通过网络发送的数据报的状态以及在部分数据报被丢弃时处理重新发送信息的任務落在了 TCP 的肩上。
大多数用户将 TCP 和 IP 视为紧密结合的一对,但 TCP 可以而且经常与其他传输协议一起使用。
例如,TCP 或其部分内容用于文件传输协议 (FTP) 和简单邮件传输协议 (SMTP),它们都不使用 IP。
传输控制协议为 IP 层和上层提供了大量的服务。最重要的是,它为上层提供了一个面向连接的协议,使应用程序能够确保通过网络发送的数据报完整无缺地接收。在这种情况下,TCP 充当消息验证协议,提供可靠的通信。如果数据报损坏或丢失,通常是 TCP(而不是更高层中的应用程序)处理重新传输。
TCP 不是软件。它是一个通信协议。
TCP 管理来自更高层的 datagram 的流,以及来自 IP 层的传入 datagram。它必须确保优先级和安全性得到尊重。TCP 必须能够处理上面某个应用程序的终止,该应用程序正在等待传入 datagram,以及较低层中的故障。TCP 还必须维护一个状态表,其中包含所有进出 TCP 层的数据流。将这些服务隔离在一个单独的层中,使得应用程序可以在不考虑流控制或消息可靠性的情况下进行设计。如果没有 TCP 层,每个应用程序都必须自己实现这些服务,这将浪费资源。
TCP 位于传输层,位于 IP 之上,但位于上层及其应用程序之下,如下图所示。TCP 仅驻留在实际处理 datagram 的设备上,确保 datagram 已从源机器传送到目标机器。它不驻留在仅路由 datagram 的设备上,因此网关中没有 TCP 层。这是有道理的,因为在网关上,数据报无需在分层模型中高于 IP 层。
图 1:TCP 提供可靠的端到端通信
因为 TCP 是一种面向连接的协议,负责确保数据报从源机器到目标机器的传输(端到端通信),所以 TCP 必须接收来自目标机器的通信消息,以确认接收数据报。虚拟电路通常用于指代两台终端机器之间进行的握手,其中大多数是简单的确认消息(确认接收或故障代码)和数据报序列号。这类似于电话通话;某人通过拨打电话号码来发起通话,该号码被接听,进行双向通话,最后某人结束通话。套接字对标识连接的两端,即虚拟电路。可以回忆起,套接字由 IP 地址和端口号组成,以标识位置。服务器使用众所周知的端口号(< 1000)来进行标准化服务(监听)。1024 以上的号码可供用户自由使用。下表列出了一些标准服务的端口号。
端口 | 协议 | 用途 |
---|---|---|
21 | FTP | 文件传输 |
23 | Telnet | 远程登录 |
25 | SMTP | 电子邮件 |
69 | TFTP | 简单文件传输协议 |
79 | Finger | 查找有关用户的信息 |
80 | HTTP | 万维网 |
110 | POP-3 | 远程电子邮件访问 |
119 | NNTP | USENET 新闻 |
字节流还是消息流?
嗯,消息边界在 TCP 中不会端到端地保留。例如,如果发送进程对 TCP 流执行了四次 512 字节的写入操作,这些数据可能会以四块 512 字节块、两块 1024 字节块、一块 2048 字节块,或其他方式交付给接收进程。接收方无法检测到写入数据的单位。TCP 实体接受来自本地进程的用户数据流,将其分解成不超过 64 KB 的片段(实际上,通常为 1460 个数据字节,以便放入具有 IP 和 TCP 头部的单个以太网帧),并将每个片段作为单独的 IP 数据报发送。当包含 TCP 数据的数据报到达机器时,它们会被传递给 TCP 实体,该实体会重建原始字节流。为简单起见,我们有时只使用*TCP* 来表示 TCP 传输实体(软件)或 TCP 协议(一组规则)。从上下文中可以清楚地知道指的是哪个。例如,在*用户将数据提供给 TCP* 中,显然指的是 TCP 传输实体。IP 层不保证数据报能够正确传送,因此 TCP 必须按需超时并重新传输数据报。到达的数据报可能顺序错误;TCP 还必须将它们按正确的顺序重新组装成消息。简而言之,TCP 必须提供大多数用户想要而 IP 没有提供的可靠性。
TCP 的特点
TCP 在每个主机系统上的进程之间提供了一个通信通道。该通道可靠、全双工且流式。为了实现此功能,TCP 驱动程序将会话数据流分解成离散的段,并为每个段附加一个 TCP 头部。IP 头部附加到此 TCP 数据包,然后将组合数据包传递到网络进行传送。此 TCP 头部包含许多字段,用于支持预期的 TCP 功能。TCP 具有以下功能特性
单播协议:TCP 基于单播网络模型,支持恰好两个方之间的数据交换。它不支持广播或多播网络模型。
连接状态:TCP 并不在网络内强制实施状态来支持连接,而是使用两个端点之间的同步状态。此同步状态是在初始连接过程中设置的,因此 TCP 可以被视为面向连接的协议。协议设计中的大部分内容旨在确保每个本地状态转换都被传达给远程方并得到远程方的确认。
可靠性:可靠性意味着在连接一端传递给 TCP 驱动程序的字节流将被传输到网络,以便字节流以与发送者生成的相同顺序,相同的字节序列呈现给远程进程。这意味着协议会检测数据流的哪些段被网络丢弃、重新排序、重复或损坏。必要时,发送方将重新传输损坏的段,以便接收方能够重建原始数据流。这意味着 TCP 发送方必须保留所有已传输数据的本地副本,直到它收到指示接收方已完成对数据的准确传输的指示。
全双工:TCP 是一种全双工协议;它允许双方在单个 TCP 连接的上下文中发送和接收数据。
流式传输:虽然 TCP 使用数据包结构进行网络传输,但 TCP 是一个真正的流式传输协议,并且应用程序级网络操作并不透明。某些协议明确地封装每个应用程序事务;对于每次写入,都必须有一个匹配的读取。以这种方式,应用程序派生的数据流到逻辑记录结构的分割在网络上保留。TCP 不保留强加于数据流的这种隐式结构,因此网络协议中没有写入和读取操作之间的配对。例如,TCP 应用程序可以将三个数据块依次写入网络连接,这些数据块可以由远程读取器在一次读取操作中收集。TCP 会话中使用的数据块(段)的大小在会话开始时协商。发送方尝试在其允许的范围内使用尽可能大的段大小来进行数据传输,这些范围包括接收方的最大段大小、配置的发送方的最大段大小以及网络路径(路径最大传输单元 [MTU])支持的最大非分段数据包大小。路径 MTU 定期刷新,以适应 TCP 连接处于活动状态时网络中可能发生的任何更改。
速率自适应:TCP 也是一种速率自适应协议,因为数据传输速率旨在适应网络中普遍存在的负载条件并适应接收方的处理能力。没有预定的 TCP 数据传输速率;如果网络和接收方都有额外的可用容量,则 TCP 发送方将尝试将更多数据注入网络,以占用此可用空间。相反,如果出现拥塞,TCP 发送方将降低其发送速率以允许网络恢复。此自适应功能试图在不触发持续数据丢失的情况下实现尽可能高的数据传输速率。
TCP 报头结构
[edit | edit source]TCP 段作为 Internet 数据报发送。Internet 协议报头包含多个信息字段,包括源主机地址和目标主机地址。TCP 报头紧随 Internet 报头,提供特定于 TCP 协议的信息。这种划分允许 TCP 以外的其他主机级别协议的存在。
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Port | Destination Port | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Sequence Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Acknowledgment Number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | |U|A|P|R|S|F| | | Offset| Reserved |R|C|S|S|Y|I| Window | | | |G|K|H|T|N|N| | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | Urgent Pointer | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ TCP Header Format Note that one tick mark represents one bit position.
源端口:16 位 源端口号。
目标端口:16 位 目标端口号。
序列号:32 位 此段中第一个数据字节的序列号(除非存在 SYN)。如果存在 SYN,则序列号是初始序列号 (ISN),第一个数据字节是 ISN+1。
确认号:32 位 如果设置了 ACK 控制位,则此字段包含段发送方预期接收的下一个序列号的值。一旦建立连接,它就会始终被发送。
数据偏移:4 位 TCP 报头中的 32 位字数。这指示数据从何处开始。TCP 报头(即使包含选项)也是 32 位的整数倍。
保留:6 位 为将来使用而保留。必须为零。
控制位:6 位(从左到右)
URG:紧急指针字段有效
ACK:确认字段有效
PSH:推送功能
RST:重置连接
SYN:同步序列号
FIN:发送方没有更多数据
窗口:16 位 从确认字段中指示的第一个字节开始,段发送方愿意接受的数据字节数。
校验和:16 位 校验和字段是报头和文本中所有 16 位字的按位取反和的按位取反。如果段包含奇数个要进行校验和的报头和文本字节,则最后一个字节在右侧用零填充以形成一个 16 位字,用于校验和目的。填充不会作为段的一部分传输。在计算校验和时,校验和字段本身将被替换为零。
校验和还涵盖一个 96 位伪报头,该伪报头概念上位于 TCP 报头的前面。此伪报头包含源地址、目标地址、协议和 TCP 长度。这使 TCP 免受错误路由段的攻击。此信息位于 Internet 协议中,并在 TCP/网络接口上的调用参数或结果中在 TCP 上传输。
TCP 长度是 TCP 报头长度加上数据长度(以字节为单位)(这不是显式传输的量,而是计算出来的),它不包括伪报头的 12 个字节。
紧急指针:16 位 此字段将紧急指针的当前值传达为相对于此段中的序列号的正偏移量。紧急指针指向紧随紧急数据的字节的序列号。此字段仅在设置了 URG 控制位的段中被解释。
选项:可变 选项可能占用 TCP 报头末尾的空间,并且长度为 8 位的倍数。所有选项都包含在校验和中。选项可以从任何字节边界开始。选项格式有两种情况
情况 1:一个选项种类字节。
情况 2:一个选项种类字节、一个选项长度字节以及实际的选项数据字节。选项长度计算选项种类和选项长度这两个字节以及选项数据字节。请注意,选项列表可能比数据偏移字段暗示的要短。超过结束选项选项的报头内容必须是报头填充(即零)。
TCP 必须实现所有选项
Ethereal 捕获
可以使用 Ethereal 捕获查看 TCP 数据包。下面捕获了一个这样的 TCP 数据包。请注意,ACK 标志和 PUSH 标志设置为“1”。
TCP 中的通信
[edit | edit source]在 TCP 可以用于任何实际有用的目的(即发送数据)之前,必须在希望通信的两个设备之间建立连接。此过程通常称为连接建立,它涉及交换消息,使两个设备从其初始连接状态 (CLOSED) 转变为正常操作状态 (ESTABLISHED)。
连接建立功能
连接建立过程实际上在创建适合数据交换的连接时完成了以下几件事
联系和通信:客户端和服务器通过相互发送消息来相互联系并建立通信。在此之前,服务器通常甚至不知道它将与哪个客户端进行通信,因此它是在连接建立期间发现这一点的。
序列号同步:每个设备都让另一个设备知道它希望用于其第一次传输的初始序列号。
参数交换:两个设备交换控制 TCP 连接操作的某些参数。
用于连接建立的控制消息:SYN 和 ACK
TCP 使用控制消息来管理联系和通信过程。但是,没有特殊的 TCP 控制消息类型;所有 TCP 消息都使用相同的段格式。TCP 报头中的一组控制标志指示段是用于控制目的还是仅仅用于传输数据。在使用控制消息时,以下标志会发生变化。
SYN:此位表示段用于初始化连接。SYN 代表同步,指的是上面提到的序列号同步。
ACK:此位表示发送段的设备正在传输对其已接收的消息(如 SYN)的确认。
正常的连接建立:“三次握手”
为了建立连接,每个设备必须发送 SYN 并从另一个设备接收其 ACK。因此,从概念上讲,需要在设备之间传递四条控制消息。但是,当可以同时通信两者时,在单独的消息中发送 SYN 和 ACK 是低效的。因此,在连接建立的正常事件序列中,通过设置两个相关位(一条消息有时称为 SYN+ACK),其中一个 SYN 和一个 ACK 会一起发送。这样总共需要三条消息,因此该连接过程被称为三次握手。
Key Concept: The normal process of establishing a connection between a TCP client and server involves three steps:
客户端发送一个 SYN 消息;服务器发送一条消息,该消息包含对客户端 SYN 的 ACK 以及服务器的 SYN;然后客户端发送对服务器 SYN 的 ACK。这被称为 TCP 三次握手。
连接在其生命周期中经过一系列状态。
这些状态是:LISTEN、SYN-SENT、SYN-RECEIVED、ESTABLISHED、FIN-WAIT-1、FIN-WAIT-2、CLOSE-WAIT、CLOSING、LAST-ACK、TIME-WAIT 和虚构状态 CLOSED。CLOSED 是虚构的,因为它代表没有 TCB,因此没有连接的状态。简而言之,这些状态的含义是
LISTEN - 代表等待来自任何远程 TCP 和端口的连接请求。
SYN-SENT - 代表在发送连接请求后等待匹配的连接请求。
SYN-RECEIVED - 代表在接收和发送连接请求后等待确认的连接请求确认。
ESTABLISHED - 代表一个开放的连接,接收到的数据可以传递给用户。连接数据传输阶段的正常状态。
FIN-WAIT-1 - 代表等待来自远程 TCP 的连接终止请求,或先前发送的连接终止请求的确认。
FIN-WAIT-2 - 代表等待来自远程 TCP 的连接终止请求。
CLOSE-WAIT - 代表等待来自本地用户的连接终止请求。
CLOSING - 代表等待来自远程 TCP 的连接终止请求确认。
LAST-ACK - 代表等待先前发送给远程 TCP 的连接终止请求的确认(其中包括对其连接终止请求的确认)。
TIME-WAIT - 代表等待足够的时间过去以确保远程 TCP 收到了对其连接终止请求的确认。
CLOSED - 代表完全没有连接状态。
TCP 连接响应事件从一种状态转换到另一种状态。这些事件是用户调用、OPEN、SEND、RECEIVE、CLOSE、ABORT 和 STATUS;传入的段,特别是那些包含 SYN、ACK、RST 和 FIN 标志的段;以及超时。
图 6 中的状态图仅说明状态变化,以及导致的事件和产生的动作,但既不涉及错误条件,也不涉及与状态变化无关的动作。在后面的部分,将提供更多关于 TCP 对事件反应的细节。
Key Concept: If one device setting up a TCP connection sends a SYN and then receives a SYN from the other one before its SYN is acknowledged, the two devices perform a simultaneous open, which consists of the exchange of two independent SYN and ACK message sets. The end result is the same as the conventional three-way handshake, but the process of getting to the ESTABLISHED state is different. The possibility of collision normally occurs in Peer-2-Peer connection.
缓冲区管理 当发送方(假设在我们这里是指客户端)要建立连接时,数据包会进入传输缓冲区。数据包应该附带一些序列号。发送方选择序列号以尽量减少使用已使用序列号的风险。客户端使用该序列号和数据以及数据包长度字段发送数据包。服务器在收到数据包后,会发送下一个预期序列号的 ACK。它还会发送包含其自身序列号的 SYN。
客户端在收到两条消息(SYN 和 ACK)后,会向接收方发送 ACK,ACK 包含接收方下一个预期的序列号。因此,在客户端和服务器之间建立了序列号。现在,它们已准备好进行数据传输。即使在发送数据时,也会遵循相同的序列号概念。
TCP 传输策略
TCP 中的窗口管理不像大多数数据链路协议那样直接与确认相关联。例如,假设接收方有一个 4096 字节的缓冲区,如下图所示。如果发送方传输一个 2048 字节的段,该段被正确接收,接收方将确认该段。但是,由于它现在只有 2048 字节的缓冲区空间(直到应用程序从缓冲区中删除一些数据),它将从下一个预期字节开始宣布 2048 的窗口大小。
现在发送方传输另外 2048 字节,这些字节被确认,但宣布的窗口大小为 0。发送方必须停止,直到接收主机上的应用程序进程从缓冲区中删除了一些数据,此时 TCP 可以宣布一个更大的窗口大小。
当窗口大小为 0 时,发送方通常不能发送段,但有两个例外。首先,可以发送紧急数据,例如,允许用户终止在远程机器上运行的进程。其次,发送方可以发送一个 1 字节的段,以使接收方重新宣布下一个预期字节和窗口大小。TCP 标准明确提供此选项以防止在窗口公告丢失时发生死锁。
发送方不需要在应用程序传入数据时立即传输数据。接收方也不需要尽快发送确认。当前 2 KB 的数据传入时,TCP 知道它有一个 4 KB 的可用窗口,因此,只要将数据缓冲起来,直到另有 2 KB 的数据传入,就可以完全正确地传输一个 4 KB 的有效载荷段。这种自由可以被利用来提高性能。
考虑一个与交互式编辑器建立的 telnet 连接,该编辑器对每个按键做出反应。在最坏的情况下,当一个字符到达发送方的 TCP 实体时,TCP 创建一个 21 字节的 TCP 段,它将其交给 IP 发送为一个 41 字节的 IP 数据报。在接收方,TCP 立即发送一个 40 字节的确认(20 字节的 TCP 头部和 20 字节的 IP 头部)。稍后,当编辑器读取了该字节时,TCP 发送一个窗口更新,将窗口向右移动 1 个字节。这个数据包也是 40 字节。最后,当编辑器处理完该字符后,它将该字符作为 41 字节的数据包进行回显。总共使用了 162 字节的带宽,并为每个键入的字符发送了四个段。当带宽稀缺时,这种做事方式是不受欢迎的。
许多 TCP 实现使用的一种优化这种状况的方法是将确认和窗口更新延迟 500 毫秒,以期获得一些可以搭便车的自由数据。假设编辑器在 500 毫秒内进行回显,现在只需要发送一个 41 字节的数据包回远程用户,从而将数据包数量和带宽使用量减半。尽管此规则减少了接收方对网络造成的负载,但发送方仍然通过发送包含 1 字节数据的 41 字节数据包而低效地运行。一种减少这种使用的方法被称为 Nagle 算法(Nagle,1984)。Nagle 建议的方法很简单:当数据以每次一个字节的速度传入发送方时,只需发送第一个字节并缓冲其余所有字节,直到确认挂起的字节。然后将所有缓冲的字符在一个 TCP 段中发送,并开始再次缓冲,直到它们都被确认。如果用户输入速度很快,而网络速度很慢,则每个段中可能会有大量字符,从而大大减少了带宽的使用量。该算法还允许在有足够的数据流入以填满一半窗口或最大段时发送新的数据包。
Nagle 算法被 TCP 实现广泛使用,但有时最好禁用它。特别是,当通过互联网运行 X 窗口应用程序时,必须将鼠标移动发送到远程计算机。(X 窗口系统是大多数 UNIX 系统中使用的窗口系统。)将它们收集起来以突发形式发送会导致鼠标光标移动不稳定,从而使用户感到不满意。
另一个可能降低 TCP 性能的问题是愚蠢窗口综合征。当数据以大块形式传递到发送方的 TCP 实体,但接收方的一个交互式应用程序一次读取 1 个字节的数据时,就会出现此问题。要了解这个问题,请查看下图。最初,接收方上的 TCP 缓冲区已满,并且发送方知道这一点(即窗口大小为 0)。然后,交互式应用程序从 TCP 流中读取一个字符。此操作使接收方的 TCP 很高兴,因此它向发送方发送一个窗口更新,告诉它可以发送 1 个字节。发送方照办,发送了 1 个字节。缓冲区现在已满,因此接收方确认 1 字节段,但将窗口设置为 0。这种行为可以永远持续下去。
Clark 的解决方案是阻止接收方发送 1 字节的窗口更新。相反,它被迫等待直到它有足够的可用空间,然后才宣布可用空间。具体来说,接收方不应该发送窗口更新,直到它能够处理在建立连接时宣布的最大段大小,或者直到它的缓冲区为空一半,以较小者为准。
此外,发送方也可以通过不发送小段来提供帮助。相反,它应该尝试等待直到它在窗口中累积了足够的可用空间以发送一个完整的段,或者至少发送一个包含接收方缓冲区大小一半的段(它必须从过去收到的窗口更新模式中估计此值)。
Nagle 算法和 Clark 对愚蠢窗口综合征的解决方案是互补的。Nagle 试图解决发送应用程序以每次一个字节的速度将数据传递给 TCP 造成的问题。Clark 试图解决接收应用程序以每次一个字节的速度从 TCP 中吸取数据的问题。两种解决方案都是有效的,可以协同工作。目标是让发送方不要发送小段,接收方不要请求它们。
接收方的 TCP 可以进一步提高性能,而不仅仅是大块地进行窗口更新。像发送方的 TCP 一样,它也可以缓冲数据,因此它可以阻塞来自应用程序的 READ 请求,直到它有大量数据可提供。这样做减少了对 TCP 的调用次数,因此减少了开销。当然,它也增加了响应时间,但对于非交互式应用程序(如文件传输),效率可能比对单个请求的响应时间更重要。另一个接收方的问题是,如何处理乱序段。接收方可以自行决定保留或丢弃它们。当然,只有在接收了确认的字节之前的所有数据时才能发送确认。如果接收方收到段 0、1、2、4、5、6 和 7,它可以确认所有字节,直到并包括段 2 中的最后一个字节。当发送方超时时,它将重新传输段 3。如果接收方缓冲了段 4 到 7,则在收到段 3 后,它可以确认所有字节,直到段 7 的末尾。
建立连接
只有在两台机器之间不存在套接字连接,并且两台机器都同意连接,并且两台机器都有足够的 TCP 资源来为连接提供服务时,才能在两台机器之间建立连接。如果任何一个条件不满足,则无法建立连接。连接的接受可以由应用程序或系统管理例程触发。
当建立连接时,它将被赋予某些属性,这些属性在连接关闭之前有效。通常,这些将是优先级值和安全值。当连接正在建立过程中时,这两个应用程序会就这些设置达成一致。
在大多数情况下,两个应用程序都期望建立连接,因此它们会发出主动或被动打开请求。下图显示了 TCP 打开的流程图。该过程从机器 A 的 TCP 接收来自其 ULP 的连接请求开始,它会向机器 B 发送一个主动打开原语。构建的段将设置 SYN 标志(设置为 1),并且将分配一个序列号。该图用符号 SYN SEQ 50 表示,表示 SYN 标志已打开,序列号(初始发送序列号或 ISS)为 50。(可以选择任何数字。)
机器 B 上的应用程序将向其 TCP 发出被动打开指令。当收到 SYN SEQ 50 段时,机器 B 的 TCP 将向机器 A 发送一个确认,序列号为 51。机器 B 还将设置自己的初始发送序列号。该图将此消息显示为 ACK 51;SYN 200 表示该消息是一个具有序列号 51 的确认,它已设置了 SYN 标志,并且 ISS 为 200。
收到后,机器 A 会发送自己的确认消息,并将其序列号设置为 201。这在图中显示为 ACK 201。然后,在打开和确认连接后,机器 A 和机器 B 都通过 ULP 向请求应用程序发送连接打开消息。
如前所述,远程机器不需要发出被动打开指令。在这种情况下,发送机器将提供发送和接收套接字号,以及优先级、安全性和超时值。两个应用程序同时请求主动打开是常见的。这很容易解决,尽管它确实需要更多的网络流量。
数据传输
传输信息很简单,如下图所示。对于机器 A 的 TCP 从 ULP 接收到的每个数据块,TCP 会将其封装并将其发送到机器 B,并使用递增的序列号。机器 B 接收到消息后,将使用一个段确认来确认它,该确认会增加下一个序列号(因此表示它已接收所有直到该序列号的数据)。图示显示了仅传输了一个信息段 - 每种方式一个。
TCP 数据传输服务实际上包含六种不同的子服务
全双工:允许连接的两端随时传输,即使是同时传输。
及时性:使用计时器确保数据在合理的时间内传输。
有序:从一个应用程序发送的数据将在另一端的接收顺序相同。尽管数据报可能通过 IP 无序接收,但 TCP 会在将消息传递到更高层之前按正确顺序重新组装消息,从而实现这一点。
标记:所有连接都具有商定的优先级和安全值。
流量控制:TCP 可以使用缓冲区和窗口限制来调节信息流。
错误校正:校验和确保数据没有错误(在校验和算法的限制范围内)。
关闭连接
要关闭连接,其中一个 TCP 会从 ULP 接收一个关闭原语,并发出一个设置了 FIN 标志的消息。这在图 8 中显示。在图中,机器 A 的 TCP 使用下一个序列号将关闭连接的请求发送到机器 B。然后,机器 B 会发送一个确认请求和其下一个序列号的确认。在此之后,机器 B 将通过其 ULP 将关闭消息发送到应用程序,并等待应用程序确认关闭。此步骤并非严格必要;TCP 可以无需应用程序批准就关闭连接,但一个行为良好的系统会通知应用程序状态的变化。
在从应用程序收到关闭连接的批准后(或请求超时后),机器 B 的 TCP 会向机器 A 发送一个带有 FIN 标志的段。最后,机器 A 确认关闭,连接终止。
当一方关闭套接字时,可能会突然终止连接。这可以在不通知另一台机器的情况下完成,也不考虑两台机器之间传输的任何信息。除了由于故障或电源中断造成的突然关闭之外,用户、应用程序或系统监控例程也可以启动突然关闭,该例程认为连接值得终止。连接的另一端可能直到尝试发送消息并且计时器超时时才会意识到突然终止已经发生。
为了跟踪所有连接,TCP 使用一个连接表。每个现有连接在表中都有一个条目,显示端到端连接的信息。下面显示了 TCP 连接表的布局 -
每列的含义如下
状态:连接的状态(关闭、关闭中、侦听、等待等)。
本地地址:连接的 IP 地址。处于侦听状态时,此值将设置为 0.0.0.0。
本地端口:本地端口号。
远程地址:远程的 IP 地址。
远程端口:远程连接的端口号。
我们知道 TCP 提供了可靠的数据传输。但是,它如何知道何时重新传输已经传输的数据包。确实,接收者使用下一个预期的序列号来确认接收到的数据包。但是,如果发送者没有收到任何 ACK 会怎么样。
考虑以下两种情况
未收到 ACK:在这种情况下,接收者确实会传输累积 ACK,但此帧在中途丢失。发送者通常会在将发送的数据包从其缓冲区中刷新之前等待此累积 ACK。但为此,它必须开发一些机制,使发送者可以在 ACK 持续很长时间未收到时采取一些措施。这里用于此目的的机制是计时器。TCP 在传输数据包后立即设置一个计时器。如果在超时之前收到 ACK,则 TCP 会将这些数据包从其缓冲区中刷新以腾出空间。如果在超时之前没有收到 ACK,则在这种情况下,TCP 会再次重新传输数据包。但是,这个超时间隔是从哪里选择的。好吧,我们很快就会看到找出这个间隔的过程。
收到重复 ACK:在这种情况下,接收者会多次向发送者发送同一个数据包的 ACK。但是,有没有想过为什么会这样?好吧,这些事情有时可能由于网络问题而发生,但是如果接收者确实收到 2-3 次以上的 ACK,那么就有一些含义与这个问题相关联。所有这些问题都从接收者端开始。接收者会一直向接收到的帧发送 ACK。这个 ACK 具有累积性。这意味着接收者有一个缓冲区。用于发送累积 ACK 的算法可以取决于填充或剩余的缓冲区量,或者它可能取决于计时器。通常,计时器被设置,以便在特定时间间隔后,接收者会发送累积 ACK。但是,如果发送者的速率很高怎么办。在这种情况下,接收者缓冲区会填满,之后它将失去存储来自发送者端的任何更多数据包的能力。在这种情况下,接收者会继续发送重复的 ACK,这意味着缓冲区已满,此后不再接受任何数据包。此消息有助于发送者控制流量速率。
整个过程使 TCP 成为一个自适应流量控制协议。这意味着在出现拥塞时,TCP 会调整其流量速率。更多内容将在拥塞控制主题中介绍。此外,TCP 中没有负 ACK。上面的两种情况向发送者传达了有关接收者状态的正确消息。现在让我们关注 TCP 如何选择超时间隔。
选择超时间隔
计时器是根据数据包从发送方到接收方完成往返所需的时间来选择的。这种往返时间被称为 RTT。但条件,即 RTT 并不总是保持不变。事实上,RTT 会随时间发生很大的变化。因此,需要将一些平均量包含在超时间隔的计算中。以下是所遵循的过程。
1. 基于先前结果计算平均 RTT。(运行平均值)
2. 测量特定时间点的 RTT,此值取决于当时的网络状况和拥塞。(测量值)
3. 计算超时间隔
0.8*(Running avg. ) + (1- 0.8)*(Measured)
值 0.8 可以根据需要进行更改,但必须小于 1。
4. 为获得更准确的结果,可以重复此过程多次。
因此,我们现在已经获得了数据包完成往返所需的平均值。为了选择超时间隔,需要将此值乘以某个因子,以创建一些余量。
5. 因此,
超时间隔 = 2 * (步骤 4 中得到的数值)
如果我们继续绘制运行平均值和特定时间的测量值的图形,我们会发现运行平均值几乎保持不变,而测量值则波动更大。以下是绘制的两个值的图形。这解释了为什么运行平均值要乘以一个大于用于乘以测量时间的数值的数值。
用户数据报协议 (UDP) 和传输控制协议 (TCP) 是 TCP/IP 协议套件中传输层的“兄弟”。它们执行相同的作用,在应用程序和互联网协议 (IP) 的数据移动功能之间提供一个接口,但它们以截然不同的方式进行。因此,这两种协议为更高层的协议提供了选择,允许它们根据自己的需求选择合适的协议。
下表有助于说明这两种协议最基本的重要属性及其对比。
这里的练习题包括作业题及其解答。这将有助于学生掌握 TCP 的概念,并鼓励他们从 Kurose 和 Tanenbaum 的书中寻找更多练习题。
1) UDP 和 TCP 使用 1 的补码进行校验和。假设您有以下三个 8 位字节:01010101、01110000、01001100。这三个 8 位字节之和的 1 的补码是多少?(请注意,尽管 UDP 和 TCP 在计算校验和时使用 16 位字,但对于此问题,您被要求考虑 8 位加数。)展示所有步骤。为什么 UDP 会取和的 1 的补码;也就是说,为什么不直接使用和?在 1 的补码方案中,接收方如何检测错误?一个比特错误有可能不被检测到吗?两个比特错误呢?
解答: 01010101 + 01110000 + 11000101 = 110001010
10001010 的 1 的补码 = 校验和 = 01110101。
在接收方,将 3 条消息和校验和加在一起以检测错误。和始终应该只包含二进制 1。如果和中包含 0 项,接收方就知道存在错误。接收方将检测到 1 位错误。但对于 2 位错误并非总是如此,因为两个不同的位可能会改变,但和可能仍然相同。
2) 回答以下问题的正确或错误,并简要说明您的答案
a) 使用 SR 协议,发送方有可能收到超出其当前窗口的报文的 ACK。
正确。考虑这样一个场景:发送方发送的第一个数据包在计时器超时后没有收到 ACK。因此它将再次发送数据包。在此期间,收到第一个数据包的 ACK。因此发送方清空其缓冲区并用新的数据包填充缓冲区。在此期间,可能会收到第二个帧的 ACK。因此,即使数据包超出当前窗口,也可能会收到 ACK。
b) 使用 GBN,发送方有可能收到超出其当前窗口的报文的 ACK。
正确。对于 (a) 提供的相同论据也适用于这里。
c) 交替比特协议与发送方和接收方窗口大小为 1 的 SR 协议相同。
正确。交替比特协议将 0 和 1 视为交替的 ACK。这里,累积 ACK 不可能,因为必须在收到每个数据包后发送 ACK。因此,SR 协议开始表现得像交替比特协议。
d) 交替比特协议与发送方和接收方窗口大小为 1 的 GBN 协议相同。
正确。相同的论据也适用于这里。
3) 考虑 TCP 用于估计 RTT 的位置。假设 a=0.1,让样本 RTT1 为最近的样本 RTT,让样本 RTT2 为次近的样本 RTT,依此类推。
a) 对于给定的 TCP 连接,假设已返回四个确认,对应的样本 RTT 为样本 RTT4、样本 RTT3、样本 RTT2、样本 RTT1。用四个样本 RTT 表示估计的 RTT。
b) 针对 n 个样本 RTT 推广您的公式。
c) 对于 (b) 中的公式,让 n 趋于无穷大。说明为什么这种平均过程被称为指数移动平均。
解答
a)
估计的 RTT1 = 样本 RTT1
估计的 RTT2 = (1-a)估计的 RTT1 + a样本 RTT2 = (1-a)样本 RTT1 + a样本 RTT2
估计的 RTT3 = (1-a)估计的 RTT2 + a样本 RTT3 = (1-a)2样本 RTT1 + (1-a)a样本 RTT2 + a样本 RTT3''
估计的 RTT4 = (1-a)估计的 RTT3 + a样本 RTT4 = (1-a)3样本 RTT1 + (1-a)2a样本 RTT2 + (1-a)a样本 RTT3 + a样本 RTT4
b)
估计的 RTTn = (1-a)(n-1)样本 RTT1 + (1-a)(n-2)a样本 RTT2 + (1-a)(n-3)a样本 RTT3 +... (1-a)a样本 RTTn-1 + a样本 RTTn
4) 我们从文本中了解到,TCP 必须收到三个重复的 ACK 才会执行快速重传。您认为 TCP 设计人员为什么选择不在收到第一个重复的 ACK 后执行快速重传?
解答:假设发送方发送 3 个连续的数据包 1、2 和 3。接收方收到 1 后,立即发送其 ACK。假设由于重新排序,接收方收到 3 而不是 2。由于接收方没有收到 2,因此它再次发送 1 的 ACK。因此,发送方收到了 1 的第二个 ACK。它仍然继续等待。现在,当接收方收到 2 时,它发送 ACK 2,然后发送 3。因此,在重新传输数据包之前等待超过 2 个 ACK 始终是安全的。
5) 您认为为什么 TCP 避免测量重新传输段的样本 RTT?
解答:让我们看看如果 TCP 测量重新传输段的样本 RTT 会发生什么问题。假设源发送数据包 P1,P1 的计时器超时,然后源发送 P2,即相同数据包的新副本。假设源测量 P2(重新传输的数据包)的样本 RTT。最后假设在传输 P2 后不久,收到 P1 的确认。源将错误地将此确认视为 P2 的确认,并计算出不正确的样本 RTT 值。
与 TCP 不同,UDP 不会在发送数据之前建立连接,它只是发送数据。因此,UDP 被称为“无连接”。UDP 数据包通常被称为“数据报”。DNS 服务是 UDP 运行的一个示例。DNS 服务器使用 UDP 发送和接收 DNS 请求。
在本节中,我们必须了解用户数据报协议。它是一个传输层协议。本节将介绍 UDP 协议、其报头结构以及它建立网络连接的方式。
如图 1 所示,用户数据报协议 (UDP) 是一个支持网络应用程序的传输层协议。它位于“会话”层之下,在开放式系统互联模型 (OSI) 中位于 IP(互联网协议)之上。该协议类似于 TCP(传输控制协议),后者用于视频会议系统等客户端/服务器程序,但 UDP 是无连接的。
图 1:OSI 层模型中的 UDP
'图 2:UDP
UDP 是一个无连接且不可靠的传输协议。两个端口用于识别源机器和目标机器中的端点。当不需要可靠的交付时,使用用户数据报协议来代替 TCP。但是,UDP 从未使用于发送重要的数据,例如网页、数据库信息等。视频、音频等流媒体使用 UDP,因为它速度快。
为什么 UDP 比 TCP 更快?
UDP 比 TCP 更快的原因是它没有流量控制。UDP 不进行任何错误检查、错误校正或确认。UDP 只关注速度。因此,当通过互联网发送的数据受到冲突的影响时,就会存在错误。
UDP 数据包被称为用户数据报,具有 8 字节的报头。用户数据报的格式如图 3 所示。在用户数据报中,前 8 个字节包含报头信息,其余字节包含数据。
图 3:UDP 数据报
源端口号:这是源主机使用的端口号,用于传输数据。它是一个 16 位长整数。因此,端口号的范围在 0 到 65,535 之间。
目标端口号:这是目标主机使用的端口号,用于接收数据。它也是一个 16 位长整数,并且与源主机具有相同的端口号范围。
长度:长度字段是一个 16 位字段。它包含用户数据报、报头和数据的总长度。
校验和:UDP 校验和是可选的。它用于检测数据的错误。如果该字段为零,则不计算校验和。如果计算了真正的校验和,则该字段包含 1。
UDP 的特点
UDP 的特点如下。
• 端到端。UDP 可以识别运行在计算机上的特定进程。
• 不可靠的、无连接的传递(例如:美国邮政服务):
UDP 使用无连接的通信设置。在这种情况下,UDP 不需要在发送数据之前建立连接。通信仅由数据段本身组成。
• 与 IP 相同的尽力而为语义
• 无确认、无排序、无流量控制
• 可能会丢失、重复、延迟、乱序或丢失连接
• 快速、低开销
1. 适用于可靠的本地网络
2. RTP(实时传输协议)
在接收数据后,计算机必须有一些机制来处理它。假设用户打开了三个应用程序,例如一个网页浏览器、一个 Telnet 会话和一个 FTP 会话。这三个应用程序都通过网络传输数据。因此,应该有一些机制供操作系统确定哪些流量是针对哪个应用程序的。为了处理这种情况,使用了网络端口。可用的端口范围是 0 到 65535。其中,0 到 1023 是众所周知的端口,1023 到 49151 是注册端口,而 49152 到 65535 是动态端口。
图 4:端口
UDP 使用的众所周知的端口列表
图 5:UDP 使用的端口列表
它包含四个部分:源端口、目标端口、长度和校验和。
图 6:UDP 报头
源端口
源端口是一个可选字段。当使用时,它指示发送进程的端口,并且在没有其他信息的情况下,可以假定为应将回复地址发送到的端口。如果不使用,则插入值零。
目标端口
它是发送数据的端口号。
长度
它包含 UDP 报头和数据的长度。
该用户数据报的长度(以八位字节为单位),包括该报头和数据。长度的最小值为八。
校验和
校验和的主要目的是错误检测。它保证消息到达正确的目的地。为了验证校验和,接收方必须从 IP 报头中提取这些字段。使用 12 字节的伪报头来计算校验和。
数据
它是应用程序数据或实际消息。
Ethereal 捕获
可以使用 Ethereal 捕获来查看 UDP 数据包。下面捕获并显示了一个 UDP 数据包。
图 7:Ethereal 捕获
在 UDP 连接中,客户端根据他们启动连接的程序设置唯一的源端口号。UDP 不限于一对一交互。可以使用广播或组播寻址来提供一对多交互。可以使用多个客户端与单个服务器通信来提供多对一交互。多对多交互只是这些技术的扩展。
UDP 校验和的主要目的是检测传输段中的错误。
UDP 校验和是可选的,但应始终打开。
要计算 UDP 校验和,需要将“伪报头”添加到 UDP 报头。伪报头中的字段都来自 IP 报头。它们用于接收系统以确保 IP 数据报被正确的计算机接收。通常,伪报头包含
图 8:UDP 伪报头
IP 源地址 4 字节
IP 目标地址 4 字节
协议 2 字节
UDP 长度 2 字节
发送方
1. 它将段内容视为 16 位整数的序列。
2. 将所有段加起来。我们称之为 sum。
3. 校验和:sum 的反码。(在反码中,所有 0 都转换为 1,所有 1 都转换为 0)。
4. 发送方将此校验和值放入 UDP 校验和字段中。
接收方
1. 计算校验和
2. 将所有段加起来,然后将 sum 加上发送方的校验和。
3. 检查校验和中是否存在 0 位。如果接收方的校验和包含任何 0,则检测到错误。因此,数据包会被接收方丢弃。
这里我们解释了一个简单的校验和计算。例如,假设我们有位流 0110011001100110 0110011001100110 0000111100001111
该位流被分成 16 位整数段。
因此,它看起来像这样
0110011001100110(16 位整数段)
0101010101010101
0000111100001111
第一个 16 位字的总和是
0110011001100110
0101010101010101
1011101110111011
将第三个字添加到上面的总和中得到
1011101110111011
0000111100001111
1100101011001010(所有段的总和)
现在要计算校验和,取 sum 的反码。如我之前提到的,反码是通过将所有 1 转换为 0,并将所有 0 转换为 1 来实现的。因此,发送方的校验和是:0011010100110101。
现在在接收方,再次将所有段加起来。并将 sum 加上发送方的校验和。
如果没有错误,接收方的检查结果将是:1111111111111111。
如果报头中存在任何 0 位,则校验和存在错误。因此,数据包会被丢弃。
您可能想知道为什么 UDP 在第一位提供校验和,因为许多链路层协议(包括流行的以太网协议)也提供错误检查?原因是无法保证源和目的地之间的所有链路都提供错误检查——其中一条链路可能使用不提供错误检查的协议。由于 IP 应该在几乎所有 2 层协议之上运行,因此传输层提供错误检查作为安全措施非常有用。尽管 UDP 提供错误检查,但它不会执行任何操作来从错误中恢复。UDP 的一些实现只是丢弃损坏的段;其他实现则将损坏的段连同警告一起传递给应用程序。
UDP 是一种传输层协议。UDP 是一种无连接的、不可靠的协议。UDP 不执行流量控制、错误控制或重传错误段。UDP 比 TCP 快。UDP 通常用于流式音频和视频。UDP 从未使用于重要文档,如网页、数据库信息等。UDP 传输包含 8 字节报头的段。它包含源端口、目标端口、UDP 长度和校验和。UDP 校验和用于检测传输段中的“错误”。
1. 计算以下序列的 UDP 校验和:11100110011001101101010101010101。
答案:要计算校验和,请按照以下步骤操作
1. First of all divide the bit stream on to two parts of 16-bit each. The two bit streams will be 1110011001100110 and 1101010101010101. 2. Add these two bit streams, so the addition will be: 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 ---------------------------------- 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 1 0 0 3. Now apply one's complement to this bit stream. One's complement is achieved by converting all 1s into 0s and all 0s into 1s. So, the checksum will be : 0100010001000011.
2. 关闭校验和字段的优点是什么?什么时候适合关闭校验和字段?
答案
By keeping checksum field turned off, this might save computational load and speed up data transfer. When we are transmitting data over wide area network(WAN), it is not a good idea to keep checksum off. We can keep checksum turned off when we are transmitting data over a Local Area Network(LAN),because switching infrastructure would catch transmission error in the Ethernet protocol's checksum
简介
当源发送的数据包比目的地可以处理的数据包多时,就会发生拥塞。当发生这种拥塞时,性能会下降。当目的地端的这些缓冲区填满时,就会发生拥塞。数据包通常会临时存储在源和目的地的缓冲区中,然后再转发到它们的上一层。
什么是拥塞?
假设我们正在观察目的地。如果源发送的数据包数量超过目的地缓冲区能够处理的数量,就会发生拥塞。当发生拥塞时,目的地对于到达的数据包只有两种选择:丢弃或保留。如果目的地丢弃新到达的数据包并保留旧数据包,则此机制称为“Y”模型。如果目的地丢弃旧数据包并用新数据包填充它们,则此机制称为“牛奶”模型。在这两种情况下,数据包都会被丢弃。检测拥塞的两种常见方法是超时和重复确认。
拥塞控制
拥塞控制可以用来计算发送方可以发送到网络上目的地的数据量。确定数据量并不容易,因为带宽会随着时间的推移而变化,连接会建立和断开。根据这些因素,发送方应该能够调整流量。TCP 拥塞控制算法用于检测和控制拥塞。以下是我们将要讨论的拥塞算法。
- 加性增加/乘性减少
- 慢启动
- 拥塞避免
- 快速重传
- 快速恢复
加性增加/乘性减少
此算法用于网络的发送方。拥塞窗口 SSIZE 是发送方在收到 ACK 之前可以发送到网络中的数据量。通告窗口 RSIZE 是接收方可以在网络上接收的数据量。TCP 源根据网络上的拥塞程度设置拥塞窗口。这是通过在拥塞增加时减少拥塞窗口,并在拥塞减少时增加拥塞窗口来完成的。这种机制通常被称为加性增加/乘性减少。
源根据数据包丢失来确定拥塞。数据包丢失是在发生超时时确定的。源等待超时时间以确认到达。在正常情况下,数据包不会丢失,因此源假设发生超时时发生了拥塞。每当发生超时时,源都会将 SSIZE 设置为之前值的一半。这种机制称为乘性减少。如果超时持续发生,窗口大小会一直减小,直到大小变为 1。这是因为拥塞窗口的最小值为 1。当发送方确定没有发生拥塞时,它会将拥塞窗口增加 1。这种增加在发送方收到每个成功 ACK 后发生,如下所示。File:Congestion1.jpg
慢启动
加性增加/乘性减少方法的主要缺点是,发送方在检测到拥塞时会将拥塞窗口减少一半,而对于每个成功接收的 ACK 则只增加 1。如果窗口大小很大或/和拥塞窗口大小从 1 增加,那么我们会浪费很多拥塞窗口。慢启动算法用于解决这个问题。SSIZE 是发送方在收到 ACK 之前可以发送到网络中的数据量。RSIZE 是接收方可以在网络上接收的数据量。SSTHOLD 是慢启动阈值,用于控制网络上的数据流量。当 SSIZE 小于阈值 SSTHOLD 时,使用慢启动算法。在开始时,发送方不知道要发送多少数据。它必须找到要发送多少数据。最初,SSIZE 必须小于或等于 2*SMSS 字节,并且不能超过 2 个段。随着数据包的发送,SSIZE 会呈指数级增长,直到 SSIZE 大于 SSTHOLD 或检测到拥塞。
当发送方检测到拥塞时,它会将拥塞窗口减少一半。再次,慢启动算法用于增加拥塞窗口。
拥塞避免
SIZE 是发送方在收到 ACK 之前可以发送到网络中的数据量。RSIZE 是接收方可以在网络上接收的数据量。SSTHOLD 是慢启动阈值,用于控制网络上的数据流量。当 SSIZE 大于阈值 SSTHOLD 时,使用拥塞避免算法。随着数据包的发送,SSIZE 每往返时间增加一个完整大小的段。这会一直持续到检测到拥塞。
快速重传
以上三种算法都使用超时来检测拥塞。这里的缺点是发送方需要等待超时发生。为了改进拥塞检测,发送方使用重复 ACK。每次数据包到达接收方时,接收方都会向发送方发送 ACK。当数据包以乱序到达接收方时,TCP 无法立即确认数据包包含的数据,因为前面的数据包还没有到达。接收方会发送上次发送的同一个 ACK,导致重复 ACK。这在下面说明。
从发送方的角度来看,重复 ACK 可能来自许多网络问题。发送方不能假设发送的数据包丢失,重复 ACK 可能由段重排序、ACK 复制或段复制触发。因此,发送方会等待 3 个重复 ACK 来确定数据包丢失。TCP 会重新传输看起来丢失的段,而不会等待重传计时器过期。
快速恢复
快速恢复算法控制新数据的传输,直到收到非重复 ACK。不执行慢启动的原因是,收到重复 ACK 不仅表示一个段已丢失,还表示段很可能正在离开网络。快速重传和快速恢复算法通常一起实现,如下所示:1. 当收到第三个重复 ACK 时,将 STHOLD 设置为 STHOLD = max (FlightSize / 2, 2*SMSS),其中 FlightSize 是网络中未完成数据的数量。2. 重新传输丢失的段并将 SSIZE 设置为 STHOLD 加 3*SMSS。这会人为地“膨胀”拥塞窗口,膨胀的量等于已经离开网络并且接收方已经缓冲的段数(三个)。3. 对于收到的每个额外重复 ACK,将 SSIZE 增加 SMSS。这会人为地膨胀拥塞窗口,以反映已经离开网络的额外段。4. 传输一个段,如果新的 SSIZE 值和接收方通告的窗口允许的话。5. 当下一个确认新的数据的 ACK 到达时,将 SSIZE 设置为 STHOLD(在步骤 1 中设置的值)。这被称为“缩小”窗口。此 ACK 应该是由步骤 1 中的重传引起的确认,在重传后一个 RTT 到达(虽然在接收方数据段存在显著乱序传递的情况下,它可能会更早到达)。此外,此 ACK 应该确认在丢失段和收到第三个重复 ACK 之间发送的所有中间段,如果这些段都没有丢失。
常见问题解答
什么会导致拥塞?当源发送的数据包数量超过目的地能够处理的数量时,就会发生拥塞。当发生这种拥塞时,性能会下降。当这些缓冲区在目的地侧被填满时,就会发生拥塞。数据包通常会暂时存储在源和目的地的缓冲区中,然后再转发到它们的上层。假设我们正在观察目的地。如果源发送的数据包数量超过目的地缓冲区能够处理的数量,就会发生拥塞。
当发生拥塞时会发生什么?当发生拥塞时,目的地对于到达的数据包只有两种选择:丢弃或保留。如果目的地丢弃新到达的数据包并保留旧数据包,则此机制称为“Y”模型。如果目的地丢弃旧数据包并用新数据包填充它们,则此机制称为“牛奶”模型。在这两种情况下,数据包都会被丢弃。
如何检测拥塞?检测拥塞的两种常见方法是超时和重复确认。