<linux> Sockets:TCP/IP网络基础 学习笔记01

本篇博客深入介绍了计算机网络概念、TCP/IP协议栈、数据链路层、IP地址分配、端口号和传输层(UDP与TCP)的工作原理。理解这些对于有效使用互联网套接字至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考:
The Linux Programming Interface - A Linux and UNIX System Programming Handbook (by Michael KerrisK)
chapter 58 SOCKETS: FUNDAMENTALS OF TCP/IP NETWORKS

本章提供一个介绍——计算机网络概念和TCP/IP网络协议。理解这些主题对于有效使用 Internet domain sockets是必要的,这些套接字将在下一章中描述。
从本章开始,我们开始提到各种Request for Comments(RFC)文件。在本书中讨论的每个网络协议都在一个RFC中有正式的描述。我们提供关于RFCs的更进一步的信息,以及一个特别与本书涵盖的资料相关的RFC列表,位于章节53.7。

58.1 Internets

一个互联网络internetwork,或者,更普遍地,互联网internet(小写的i),连接了不同的计算机网络,允许所有网络上的主机相互通信。也就是说,一个互联网是计算机网络的网络。术语subnetwork或者subnet,被用来指代构成互联网的网络中一个网络。一个互联网的目的是隐藏不同物理网络的细节,以便向所连接网络上的所有主机呈现一个统一的网络架构。这意味着,例如,一个单一的地址格式被用来识别互联网上的所有主机。
尽管各种互联协议已经被设计出来,TCP/IP已经成为主导的协议套件,甚至取代了以前在局域网和广域网中普遍使用的专有的网络协议。这个词Internet(大写I)是指连接全球数百万台计算机的TCP/IP网络。
TCP/IP的第一个广泛的实现出现在1983年的4.2BSD中。多个TCP/IP实现直接从BSD代码派生;其它实现,包括Linux实现,是从头开始写的,并把BSD代码的operation作为一个定义TCP/IP的operation的参考标准。

TCP/IP源于美国国防部高级研究计划局(ARPA, later DARPA, with the D for Defense) 赞助的一个项目,目的是发明一个计算机网络架构由于ARPANET,一个早期的广域网络。在1970年代,为ARPANET设计了一组新的协议。准确地说,这些协议被称为DARPA互联网协议套件,但通常它们被称为TCP/IP协议套件,或者简称为TCP/IP。
网页http://www.isoc.org/internet/history/brief.shtml提供了互联网和TCP/IP的简要历史。

图58-1显示了一个简单的互联网。在这个图中,机器tekapo是路由器router的一个例子,路由器的功能是连接一个子网到另一个子网,在他们之间传输数据。除了理解正在被使用的互联网协议以外,一个路由器还必须理解它所连接的(可能)不同子网所使用的data-link-layer协议。
在这里插入图片描述

58.2 Networking Protocols and Layers

网络协议是一组定义如何在网络上传输信息的规则。网络协议通常被组织为一系列的层,每个层建立在其下面的层上,以添加对更高层可用的特性。TCP/IP协议套件是一个分层的网络协议(如图58-2所示)。它包括互联网协议(IP)和其之上的各种协议。(实现这些不同层的代码通常被称为协议栈。)TCP/IP这个名称来源于传输控制协议(TCP)是使用最频繁的传输层协议。

我们在图58-2中省略了一系列其他TCP/IP协议,因为它们与本章无关。地址解析协议(ARP)涉及到将互联网地址映射到硬件(例如以太网)地址。The Internet Control Message Protocol (ICMP) 协议用于在网络中传递错误和控制信息。(ICMP被程序ping使用,程序ping经常被用来检查TCP/IP网络上某个特定的主机是否活跃且可见,也被traceroute使用,traceroute则用来跟踪一个IP数据包通过网络时的路径。)Internet Group Management Protocol (IGMP)被支持IP数据报的多播的主机和路由器所使用。
在这里插入图片描述
为协议分层带来强大功能和灵活性的概念之一是透明性——每个协议层都将较高层从较低层的操作和复杂性中屏蔽出来。因此,例如,一个使用TCP的应用程序只需要使用标准的套接字API,并且知道它正在使用可靠的字节流传输服务。它不需要了解TCP操作的细节。(当我们在第61.9节看套接字选项时,我们会发现这并不一直是对的;有时,应用程序确实需要知道底层传输协议操作的一些细节。)应用程序也不需要知道IP或数据链路层的操作细节。从应用程序的角度来看,它们好像是通过套接字API直接相互通信,如图58-3所示,其中虚线表示两台主机上对应的应用程序、TCP和IP实体之间的虚拟通信路径。

Encapsulation
封装是分层网络协议的一个重要原则。如图58-4所示为在TCP/IP协议层的封装的一个例子。封装的关键思想是将从较高的层传递到较低的层的信息(例如,application data, a TCP segment, or an IP datagram)被较低的层视为不透明的数据。换句话说,下层不试图解释来自上层的信息,仅仅是将该信息放在下层使用的任何类型的数据包中,并在将数据包传递到下一层之前添加它自己的特定于该层的报头。当数据从较低的层向上传递到较高的层时,就会发生相反的解包过程。

我们没有在图58-4中显示它,但是封装的概念也延伸到数据链路层,在那里IP数据报被封装在网络帧network frames内。封装也可以扩展到应用层,在应用层中,应用程序可以执行自己的数据封装。
在这里插入图片描述
在这里插入图片描述

58.3 The Data-Link Layer

图58-2中最低的一层是数据链路层,它包括设备驱动程序和到底层物理介质(如电话线、同轴电缆或光纤电缆)的硬件接口(网卡)。数据链路层涉及到在网络中的物理链路上传输数据。
为了传输数据,数据链路层将来自网络层的数据报封装成称为帧frames的单元。除了要传输的数据外,每个帧还包含一个报头,例如,包含目的地地址和帧大小。数据链路层通过物理链路传输帧,并处理来自接收方的确认。(并非所有数据链接层都使用确认。)该层也可能执行错误检测、重传和流量控制。一些数据链路层也将大型网络数据包分解成多个帧,并在接收端重新组合它们。
从应用程序编程的角度来看,我们通常可以忽略数据链路层,因为所有通信细节都是在驱动程序和硬件中处理的。
数据链路层的一个特征对我们讨论IP很重要,就是最大传输单元 maximum transmission unit (MTU)。数据链路层的MTU是该层对帧大小规定的上限。不同的数据链路层有不同的MTU。

命令netstat -i显示系统的网络接口及其MTU的列表。

58.4 The Network Layer: IP

在数据链路层之上是网络层,它负责将数据包(数据)从源主机发送到目标主机。该层执行各种任务,包括:

  • 将数据分解成足够小的片段,以便通过数据链路层传输(如果必要的话);
  • routing data across the internet; and
  • 向传输层提供服务。
    在TCP/IP协议组中,网络层的主要协议是IP。出现在4.2BSD实现中的IP版本是IP version 4 (IPv4)。在20世纪90年代早期,IP的修订版被设计出来:IP version 6 (IPv6)。两个版本之间最显著的区别是,IPv4使用32位地址标识子网和主机,而IPv6使用128位地址,因此提供了更大范围的地址分配给主机。尽管IPv4仍然是互联网上使用的IP的主要版本,但在未来几年,它应该会被IPv6取代。IPv4和IPv6都支持更高的UDP和TCP传输层协议(以及许多其他协议)。

虽然32位地址空间理论上允许分配数十亿个IPv4网络地址,地址的构造和分配方式意味着可用地址的实际数量要低得多。IPv4地址空间可能耗尽是创建IPv6的主要动机之一。
IPv6的简短历史可以在ttp://www.laynetworks.com/IPv6.htm上找到。
Pv4和IPv6的存在引出了一个问题:“IPv5呢?”从未有过这样的IPv5。每个IP数据报报头包括一个4位的版本号字段(因此,IPv4数据报在这个字段中总是有数字4),版本5被分配给了一个实验性的协议,Internet Stream Protocol. (该协议的版本2,缩写为ST-II,在RFC 1819中描述。)这种面向连接的协议最初构思于20世纪70年代,旨在支持语音和视频传输以及分布式仿真。由于IP数据报版本号5已经被分配,IPv4的后继者被分配了版本号6。

图58-2显示了一个原始套接字类型(SOCK_RAW),它允许应用程序直接与IP层通信。我们不描述原始套接字的使用,因为大多数应用程序使用传输层协议(TCP或UDP)上的socket。原始套接字在[Stevens et al., 2004]的第28章中描述。使用原始套接字的一个具有指导性的例子是sendip程序(http://www.earth.li/projectpurple/progs/sendip.html),这是一个命令行驱动的工具,允许构建和传输任意内容的IP数据报(包括构造UDP数据报和TCP段的选项)。

IP transmits datagrams
IP以datagrams (packets).的形式传输数据。在两台主机之间发送的每个数据报在网络上独立travels,可能采用不同的路由。IP数据报包括报头,其大小从20字节到60字节不等。报头包含目标主机的地址,这样数据报就可以通过网络路由到它的目的地,还包括数据包的起始地址,这样接收主机就知道数据报的起始地址。
发送主机有可能欺骗数据包的起始地址,这构成了TCP拒绝服务denial-of-service攻击的基础,称为SYN-flooding。[Lemon, 2002]描述了这种袭击的细节和现代TCP实现用来应对它的措施。
IP实现可能对其支持的数据报大小设置上限。所有IP实现必须允许数据报至少大于IP’s minimum reassembly buffer size所指定的限制。在IPv4中,这个限制是576字节;在IPv6中,是1500字节。

IP is connectionless and unreliable
IP被描述为无连接协议,因为它没有提供连接两台主机的虚拟电路的概念。IP也是一种不可靠的协议:它“竭尽全力”将数据报从发送方发送到接收方,但不能保证数据包将按照它们被传输的顺序到达,不能保证它们是不重复的,甚至不能保证它们能够到达。IP也不提供错误恢复(带有报头错误的包被静默丢弃)。可靠性必须通过使用可靠的传输层协议(例如TCP)或在应用程序本身中来提供。
IPv4为IP报头提供校验和,允许检测报头中的错误,但不为数据包内传输的数据提供任何错误检测。IPv6在IP报头中不提供校验和,依赖于更高层次的协议提供所需的错误检查和可靠性。(IPv4中UDP校验和是可选的,但通常启用;IPv6中UDP校验和是必需的。TCP校验和对于IPv4和IPv6都是强制的。)
由于某些数据链路层采用了确保可靠性的技术,或者当IP数据报通过一些采用重传的非TCP/IP网络进行隧道传输时,可能会出现重复的IP数据报。

IP may fragment datagrams
IPv4数据报最多可达65535字节。默认情况下,IPv6允许最多65575字节的数据报(40字节的报头,65535字节的数据),并为更大的数据报(所谓的jumbograms)提供了一个选项。
我们之前注意到,大多数数据链路层都对数据帧的大小施加了上限(MTU)。例如,在常用的以太网网络体系结构上,这个上限是1500字节(也就是说,比IP数据报的最大大小要小得多)。IP也定义了path MTU的概念。这是在从源到目的地的路由上穿过的所有数据链路层上的最小MTU。(实际上,以太网的MTU通常是路径中最小的MTU。)当IP数据报大于MTU时,IP将数据报分段(拆分)为适当大小的单元,以便在网络上传输。然后在最终目的地重新组装这些片段,以重新创建原始数据报。(每个IP片段本身就是一个IP数据报,其中包含一个偏移字段,给出了该片段在原始数据报中的位置。)
IP分片的发生对更高的协议层是透明的,但通常被认为是不受欢迎的 ([Kent & Mogul, 1987])。问题是,由于IP不执行重传,而且只有在所有片段到达时,数据报才能在目的地重新组装,如果任何片段丢失或包含传输错误,整个数据报将不可用。在某些情况下,这可能会导致大比例数据丢失(对于不执行重传的更高协议层,如UDP)或降低传输速率(对于执行重传的更高协议层,如TCP)。现代TCP实现采用了算法(path MTU discovery)来确定主机之间路径的MTU,相应地,它们将传送给IP的数据分解,这样IP就不会被要求传输超过这个大小的数据报。UDP不提供这样的机制,我们将在58.6.2节讨论基于UDP的应用程序如何处理IP分片的可能性。

58.5 IP Addresses

IP地址由两部分组成:网络ID(指定主机所在的网络)和主机ID(标识该网络中的主机)。

IPv4 addresses
IPv4地址由32位组成(图58-5)。当以人类可读的形式表示时,这些地址通常用点分十进制表示,地址的4个字节被写成用点分隔的十进制数,如204.152.189.116。
在这里插入图片描述
当一个组织为其主机申请一定范围的IPv4地址时,会收到一个32位的网络地址和相应的32位网络掩码。在二进制格式中,这个掩码由最左边的一个全1序列和一个全0来填充掩码的其余部分。其中1s表示该地址中包含已分配的网络ID的部分, 0s表示该地址中可被组织分配为其网络中唯一的主机ID的部分。在分配地址时决定掩码的网络ID部分的大小。由于网络ID部分总是占据掩码的最左边,下面的表示法足以指定分配的地址范围:

204.152.189.0/24

“/24”表示分配地址的网络ID部分为左24位,其余8位为主机ID。或者,我们可以说,在这种情况下,网络掩码是点分十进制格式的255.255.255.0。
拥有这个地址的组织可以为其计算机分配254个唯一的Internet地址- 204.152.189.1到204.152.189.254。两个地址不能被分配。其中之一是主机ID全为0位的地址,它被用来识别该网络本身。另一个是主机ID全为1的地址,本例中为204.152.189.255,即子网广播地址。
某些IPv4地址具有特殊含义。特殊地址127.0.0.1通常被定义为环回地址loopback address,并且按照惯例被分配主机名localhost。(网络127.0.0.0/8上的任何地址都可以指定为IPv4环回地址loopback address,但通常选择127.0.0.1。)发送到此地址的数据报实际上永远不会到达网络,而是自动循环返回,成为发送主机的输入。使用这个地址可以方便地在同一台主机上测试客户端和服务器端程序。为了在C程序中使用,为这个地址定义了整数常量INADDR_LOOPBACK。
常量INADDR_ANY是所谓的IPv4通配地址。通配IP地址对于在multihomed hosts上绑定Internet域套接字的应用程序很有用。如果多multihomed hosts上的应用程序仅将套接字绑定到其主机的一个IP地址,那么该套接字只能接收发送到该IP地址的UDP数据报或TCP连接请求。然而,我们通常希望multihomed hosts上的应用程序能够接收指定任何主机IP地址的数据报或连接请求,将套接字绑定到通配IP地址使这成为可能。SUSv3没有指定任何特定的值给INADDR_ANY,但大多数实现将其定义为0.0.0.0(全零)。
一般情况下,IPv4地址是划分子网的。子网划分将IPv4地址的主机ID部分划分为两部分:子网ID和主机ID,如图58-6所示。(主机ID的位如何划分是由本地网络管理员决定的。)子网的基本原理是,一个组织通常不会将所有主机都连接到一个单一的网络。相反,组织可以operate一组子网(“内部互联网络”),每个子网由网络ID和子网ID的组合来标识。这种组合通常称为扩展网络ID。在子网内,子网掩码的作用与前面描述的网络掩码相同,我们可以使用类似的符号来表示分配给特定子网的地址范围。
例如,假设我们分配的网络ID是204.152.189.0/24,并且我们选择将8位主机ID分成4位子网ID和4位主机ID来为这个地址范围划分子网。在这种方案下,子网掩码将由28个前导1,后面跟着4个0,并且子网ID为1的将被指定为204.152.189.16/28。在这里插入图片描述

IPv6 addresses
IPv6地址原理与IPv4类似。关键区别在于IPv6地址由128位组成,前几位是格式前缀,表示地址类型。(我们不会详细讨论这些地址类型;详见[Stevens et al., 2004] 的附录A和RFC 3513。)
IPv6地址通常是用冒号分隔的一系列的16位16进制数,如下所示:
F000:0:0:0:0:0:A:1
IPv6地址通常包括一系列的零,为了便于标记,可以使用两个冒号(::)来表示这样的序列。因此,上述地址可以改写为:
F000::A:1
只有一个双冒号表示法的实例可以出现在IPv6地址中;超过一个实例的话是会导致歧义。
IPv6也提供了相当于IPv4的环回地址(127个零,后面跟着一个1,即::1)和通配地址(全部为零,可以写成0::0或::)的等价物。
为了让IPv6应用程序允许与只支持IPv4的主机通信,IPv6提供所谓的IPv4-mapped IPv6 addresses。地址格式如图58-7所示。
在这里插入图片描述
当写一个IPv4-mapped IPv6 address时,地址的IPv4部分(即最后4个字节)用IPv4点分十进制表示。因此,与204.152.189.116等价的IPv4-mapped IPv6 address为::FFFF:204.152.189.116。

58.6 The Transport Layer

在TCP/IP套件中有两种广泛使用的传输层协议:

  • User Datagram Protocol (UDP) 是用于datagram sockets的协议
  • Transmission Control Protocol (TCP) 是用于stream sockets的协议
    在考虑这些协议之前,我们首先需要描述端口号,这是两个协议都使用的一个概念。

58.6.1端口号

传输协议的任务是向驻留在不同主机(有时在同一主机)上的应用程序提供端到端通信服务。为了做到这一点,传输层需要一种方法来区分主机上的应用程序。在TCP和UDP中,这种区别是由16位端口号提供的。

Well-known, registered, and privileged ports
一些众所周知的端口号被永久地分配给特定的应用程序(也称为服务)。例如,ssh (secure shell)守护进程使用众所周知的端口22,HTTP(用于web服务器和浏览器之间通信的协议)使用众所周知的端口80。众所周知的端口由中央机构the Internet Assigned Numbers Authority (IANA, http://www.iana.org/)分配,范围在0到1023之间。众所周知的端口号的分配取决于批准的网络规范(通常以RFC的形式)。
IANA还记录已经注册的端口registered ports,这些端口以不那么严格的方式分配给应用程序开发人员(这也意味着实现不需要为其注册的用途保证这些端口的可用性)。IANA已经注册的端口范围为1024 ~ 41951。(并非该范围内的所有端口号都已注册。)
IANA众所周知的和已经注册的端口分配信息的最新的list可以在线通过http://www.iana.org/assignments/port-numbers获得。
在大多数TCP/IP实现(包括Linux)中,0到1023之间的端口号也是有特权的,这意味着只有享有特权的(CAP_NET_BIND_SERVICE)进程可以绑定到这些端口。这可以防止普通用户实现恶意应用程序,例如将其伪装为ssh以获取密码。(有时,特权端口被称为保留端口。)
尽管具有相同编号的TCP和UDP端口是不同的实体,但通常将相同的知名端口号分配给TCP和UDP下的服务,即使通常情况下,该服务仅在其中之一下可用。该约定避免了两种协议之间的端口号混淆。

Ephemeral ports
如果应用程序没有选择一个特定的端口(即,在套接字术语中,它没有将它的套接字bind() 到一个特定的端口),那么TCP和UDP将一个唯一的临时端口(即短命的)号码分配给套接字。在这种情况下,应用程序——通常是客户机——并不关心它使用哪一个端口号,但是分配一个端口是必要的,这样传输层协议就可以识别通信端点。它也有这样的结果,通信channel另一端的对等应用程序知道如何与此应用程序通信。如果我们将一个套接字绑定到端口0,TCP和UDP也会分配一个临时端口号。
IANA将49152到65535之间的端口指定为动态端口或私有端口,目的是让本地应用程序使用这些端口,并将其指定为临时端口。但是,不同的实现从不同的范围分配临时端口。在Linux上,范围由文件/proc/sys/net/ipv4/ip_local_port_range中包含的两个数字定义(并且可以通过其修改)。

58.6.2 User Datagram Protocol (UDP)

UDP只为IP添加了两个features:端口号和数据校验和,以允许检测传输数据中的错误。
和IP一样,UDP是无连接的。因为它没有增加可靠性给IP,UDP同样也是不可靠的。如果基于UDP的应用程序需要可靠性,那么这必须在应用程序中实现。尽管有这种不可靠,我们有时可能更喜欢使用UDP而不是TCP,原因在第61.12节详细介绍。

UDP和TCP使用的校验和只有16位长,而且是简单的“add-up”校验和,它无法检测到某些类型的错误。因此,它们不能提供极强的错误检测。繁忙的Internet服务器通常每隔几天平均会发现一个未检测到的传输错误 ([Stone & Partridge, 2000]).需要更强数据完整性保证的应用程序可以使用安全套接字层Secure Sockets Layer (SSL)协议,该协议不仅提供了安全的通信,而且还提供了更严格的错误检测。或者,应用程序可以实现自己的错误控制方案。

Selecting a UDP datagram size to avoid IP fragmentation
在58.4节中,我们描述了IP分片机制,并注意到通常最好避免IP分片。TCP包含了避免IP分片的机制,而UDP没有。在UDP中,通过传输超过the MTU of the local data link的数据报,很容易导致IP分片。
基于UDP的应用程序通常不知道源主机和目标主机之间路径的MTU。为了避免IP分片,基于UDP的应用程序通常采用保守的方法,那就是保证保证传输的IP数据包小于IPv4 minimum reassembly buffer size即576字节。(这个值可能比路径MTU低。)从这576个字节中,UDP自己的报头需要8个字节,IP报头需要额外的至少20个字节,剩下的548个字节留给UDP数据报本身。在实践中,许多基于UDP的应用程序为其数据报选择更低的512字节([Stevens, 1994])。

58.6.3 Transmission Control Protocol (TCP)

TCP为两个终端(即应用程序)之间提供了一个可靠的、面向连接的、双向的字节流通信channel,如图58-8所示。为了提供这些特性,TCP必须执行本节中描述的任务。(所有这些特征的详细描述可以在[Stevens, 1994]中找到。)
在这里插入图片描述
我们使用TCP endpoint端点这个术语来表示内核为TCP连接的一端维护的信息。(通常,我们进一步缩写这个术语,例如,只写“a TCP”表示“a TCP endpoint”,或“the client TCP“表示为“the TCP endpoint maintained for the client application”。)此信息包括连接的这一端的发送和接收缓冲区,以及一些为了同步两个connected endpoints的操作而维护的状态信息。(当我们考虑第61.6.3节中的TCP状态转换图时,我们会更详细地描述这个状态信息。)In the remainder of this book, we use the terms receiving TCP and sending TCP to denote the TCP endpoints maintained for the receiving and sending applications on either end of a stream socket connection that is being used to transmit data in a particular direction。(在本书的其余部分,我们使用接收TCP和发送TCP这两个术语来表示在流套接字连接的任何一端为接收和发送应用程序维护的TCP端点,流套接字连接用于在特定方向传输数据。还是看原文比较舒服…)

Connection establishment
在通信开始之前,TCP在两个端点之间建立一个通信通道。在建立连接期间,发送方和接收方可以exchange options来发布连接的参数。

Packaging of data in segments
数据被分成若干段,每段包含一个校验和以允许检测端到端传输错误。每一段是由一个单独的IP数据报传输的。

Acknowledgements, retransmissions, and timeouts
当TCP段到达目的地没有错误时,接收TCP向发送方发送一个肯定的确认,通知发送方已成功发送的数据。如果一个数据段到达时带有错误,那么它将被丢弃,并且不发送确认。为了处理从未到达或被丢弃的数据段的可能性,发送方在每个数据段传输时启动一个计时器。如果在计时器到期前没有收到确认信息,该段将被重传。

由于发送一个网段和接收它的确认所花费的时间根据网络的范围和当前的流量负载而不同,TCP采用一种算法来动态调整重传超时时间(RTO)的大小。
receiving TCP 可能不会立即发送确认,而是等待几分之一秒,看看确认是否可以在接收方可以直接发送回发送方的任何响应中携带。(每个TCP segment包括一个确认字段,允许这样的搭载。)这种技术称为延迟delayed ACK,其目的是节省发送TCP段的时间,从而减少网络中的数据包数量,减少发送和接收主机的负载。

Sequencing
通过TCP连接传输的每个字节都被分配了一个逻辑序列号。这个数字表示该字节在连接的数据流中的位置。(连接中的两个流中的每一个都有自己的序列编号。)(Each of the two streams in the connection has its own sequence
numbering.) 当传输TCP段 segment时,它包含一个字段,该字段包含段中第一个字节的序列号。为每个segment附加序列号有多种用途:

  • 序列号允许TCP段在目的地以正确的顺序组装,然后作为一个字节流传递给应用层。(在任何时刻,发送方和接收方之间都可能有多个TCP段在传输中,这些段的到达可能是无序的。)
  • 从接收方传递回发送方的确认消息可以使用序列号来标识哪个TCP段已经收到。
  • 接收端可以使用序列号来消除重复的段。这样的重复可能是由于IP数据报的重复,也可能是由于TCP自己的重传算法,如果一个成功传送的segment的确认消息丢失了或者没有及时传递,重传算法可能会重传该segment。
    一个stream的初始序列号(ISN)不是从0开始的。它是通过一个算法生成的,该算法会increase分配给连续的TCP连接的ISN(以防止这种可能行——混淆来自该连接的前一个实体的旧的segment和该连接本身的segment.)。这个算法也被设计用来使猜测ISN变得困难。sequence号是一个32位的值,当达到最大值时,该值被替换为0。

Flow control
流量控制防止快速发送方overwhelming缓慢的接收方。为了实现流量控制,接收TCP维护一个用于接收数据的缓冲区。(每个TCP在连接建立期间会advertise这个缓冲区的大小。)当从发送TCP接收到数据时,数据在这个缓冲区中累积,当应用程序读取数据时数据将被删除。With each acknowledgement,,接收方会通知发送方其传入数据缓冲区中有多少可用空间(即发送方可以发送多少字节)。TCP流量控制算法采用了所谓的滑动窗口算法,该算法允许在发送方和接收方之间传输包含总计最多N(提供的窗口大小)字节的未确认段。如果接收TCP的输入数据缓冲区完全填满,则窗口被关闭,发送TCP停止传输。

接收方可以使用SO_RCVBUF套接字选项覆盖传入数据缓冲区的默认大小(参见socket(7)手册页)。

Congestion control: slow-start and congestion-avoidance algorithms
TCP的拥塞控制算法是为了防止快速发送者使网络过载而设计的。如果发送TCP传输数据包的速度快于它们能被中间的路由器转发的速度,路由器就会开始丢弃数据包。这可能会导致高比例的丢包率,结果是,严重的性能退化,如果发送TCP以相同的速率坚持重传这些被丢弃的segments。TCP的拥塞控制算法在以下两种情况下非常重要:

  • 在连接建立以后:在这个时候(或者一个连接在空闲了一段时间后继续传送时)发送方会立刻开始 injecting由接收方通知的窗口大小所允许的尽可能多的segments到网络。(事实上,早期TCP实现就是这么做的。)问题是,如果网络不能处理这个segment flood,发送方就有马上overwhelming网络的风险。
  • 当检测到拥塞时:如果发送TCP检测到拥塞发生,那么它必须降低传输速率。TCP检测到正在发生拥塞是基于这样的假设,由于传输错误造成的segment丢失率非常低;如果packet丢失,则认为是拥塞的原因。
    TCP的拥塞控制策略结合了两种算法:慢启动和避免拥塞。
    慢启动算法使发送TCP最初以较慢的速率发送segments,但当这些分段被接收TCP确认时,允许它以指数级的速率增加。慢启动试图阻止快速的TCP发送者overwhelming网络。然而,如果不加限制,慢启动的指数级增加传输速率,可能意味着发送者很快就会淹没网络。TCP的拥塞避免算法通过在速率增长上设置一个调控器来防止这种情况。
    在避免拥塞的情况下,在连接的开始,发送TCP会从一个小的拥塞窗口开始,来限制了它可以传输的未确认数据的数量。当发送方收到来自对等方TCP的确认时,拥塞窗口开始呈指数增长。然而,一旦拥塞窗口达到一定的阈值,相信接近网络的传输能力,它的增长成为线性,而不是指数。然而,一旦拥塞窗口达到一定的阈值,被相信接近网络的传输能力的阈值,它的增长成为线性,而不是指数。(一个对网络容量的估计是根据检测到拥塞时运行的传输速率计算得出的,或者是在连接初始建立后设置为一个固定值。)在任何时候,发送TCP将传输的数据量都受到接收TCP的advertised窗口和本地TCP的发送缓冲区的额外限制。
    通过组合,慢启动和避免拥塞算法允许发送方快速提高其传输速度到网络的可用容量,而不会超过该容量。这些算法的效果是使数据传输快速达到平衡状态,即发送方以收到接收方确认消息的速率发送数据包。

58.7 Requests for Comments (RFCs)

我们在本书中讨论的每一个Internet协议都是在RFC文档中定义的——一种正式的协议规范。RFC由RFC Editor发布(http://www.rfc-editor.org/),由Internet Society (http://www.isoc.org/)资助。

。。。

58.8 Summary

。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值