第一章 概述
- 链路层, 有时也称作数据链路层或网络接口层
- TCP(传输控制协议)为两台主机提供高可靠性的数据通信。它所做的工作包括把应用程序交给它的数据分成合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时钟等。UDP则为应用层提供一种非常简单的服务。它只是把称作数据包的分组从一台主机发送到另一台主机,但并不在保证该数据报能到达另一端。任何必需的可靠性由应用层来提供.
- 一个互连网就是一组通过相同协议族互连在一起的网络。
- 构造互连网最简单的方法是把两个或多个网络通过路由器进行连接。
- 路由器的好处是为不同类型的物理网络提供连接:以太网、令牌环网、点对点的链接和FDDI(光纤分布式数据接口)等等。
- 在TCP/IP协议族中,网络层 IP提供的是一种不可靠的服务。也就是说,它只是尽可能快地把分组从源结点送到目的结点,但是并不提供任何可靠性保证。而另一方面, TCP在不可靠的IP层上提供了一个可靠的运输层。为了提供这种可靠的服务, T C P采用了超时重传、发送和接收端到端的确认分组等机制。由此可见,运输层和网络层分别负责不同的功能。
- 连接网络的另一个途径是使用网桥,网桥是在链路层上对网络进行互连,而路由器则是在网络层上对网络进行互连。
- 由于互联网上的每个接口必须有一个唯一的 IP地址,因此必须要有一个管理机构为接入互联网的网络分配 I P地址。这个管理机构就是互联网络信息中心( Internet Network Information Centre),称作InterNIC。 InterNIC只分配网络号。
- 有三类I P地址:单播地址(目的为单个主机) 、广播地址(目的端为给定网络上的所有主机)以及多播地址。
- 封装 当应用程序用 TCP传送数据时,数据被送入协议栈中,然后逐个通过每一层直到被当作一串比特流送入网络。其中每一层对收到的数据都要增加一些首部信息(有时还要增加尾部信息(以太网帧会加尾部)) T C P传给I P的数据单元称作 T C P报文段或简称为 T C P段( TCP segment)。 I P传给网络接口层的数据单元称作 I P数据报(IP datagram)。通过以太网传输的比特流称作帧(Frame )
- 以太网数据帧的物理特性是其长度必须在 46~1500字节之间
- I P必须在生成的 I P首部中加入某种标识,以表明数据属于哪一层。为此, I P在首部中存入一个长度为8 bit的数值,称作协议域。 1表示为ICMP协议, 2表示为ICMP协议, 6表示为TCP协议, 17表示为UDP协议。
- 运输层协议在生成报文首部时要存入一个应用程序的标识符。 T C P和U D P都用一个1 6 b i t的端口号来表示不同的应用程序。TCP和UDP把源端口号和目的端口号分别存入报文首部中。
- 当使用 TCP和UDP提供相同的服务时,一般选择相同的端口号
第二章 链路层
- 链路层主要有三个目的
- 为IP模块发送和接收I P数据报
- 为ARP模块发送 ARP请求和接收 ARP应答;
- 为RARP发送RARP请求和接收RARP应答
- 它采用一种称作 CSMA / CD的媒体接入方法,其意思是带冲突检测的载波侦听多路接入
- 以太网帧
- 目的地址(6字节)
- 原地址(6字节)
- 类型字段(2个字节)
- 数据(46 ~ 1500)
- CRC CRC字段用于帧内后续字节差错的循环冗余码检验(检验和) (它也被称为 FCS或帧检验序列) 。
- 大多数的产品都支持环回接口( Loopback Interface),以允许运行在同一台主机上的客户程序和服务器程序通过 TCP / IP进行通信。 A类网络号 127就是为环回接口预留的。根据惯例,大多数系统把 I P地址127.0.0.1分配给这个接口,并命名为 localhost。一个传给环回接口的 IP数据报不能在任何网络上出现。
- 最大传输单元MTU
- 以太网数据帧1500字节
第三章 IP:网际协议
-
许多刚开始接触 TCP/IP的人对IP提供不可靠、无连接的数据报传送服务感到很奇怪。
- 不可靠( unreliable)的意思是它不能保证 IP数据报能成功地到达目的地。 IP仅提供最好的传输服务。如果发生某种错误时,如某个路由器暂时用完了缓冲区, I P有一个简单的错误处理算法:丢弃该数据报,然后发送 ICMP消息报给信源端。任何要求的可靠性必须由上层来提供(如TCP)。
- 无连接( connectionless)这个术语的意思是 IP并不维护任何关于后续数据报的状态信息。每个数据报的处理是相互独立的。这也说明, IP数据报可以不按发送顺序接收。如果一信源向相同的信宿发送两个连续的数据报(先是 A,然后是 B),每个数据报都是独立地进行路由选择,可能选择不同的路线,因此 B可能在A到达之前先到达。
-
网络字节序(大端)
- 4个字节的32 bit值以下面的次序传输:首先是 0~7 bit,其次8~15 bit,然后1 6~23 bit,最后是24~31 bit。这种传输次序称作 big endian字节序。由于T C P / I P首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。以其他形式存储二进制整数。
的机器,如little endian格式,则必须在传输数据之前把首部转换成网络字节序
- 4个字节的32 bit值以下面的次序传输:首先是 0~7 bit,其次8~15 bit,然后1 6~23 bit,最后是24~31 bit。这种传输次序称作 big endian字节序。由于T C P / I P首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。以其他形式存储二进制整数。
-
IP首部
- 普通的IP首部长为20个字节。
协议版本号(IPv4,IPv6)- 4位首部长度
- 首部占32bit字的数目。2^4(0 ~ 15) 15 * 4字节。所以首部最长60个字节。普通IP数据包字段的值是5. 5 * 4也就是20个字节。
- TOS字段包含一个3bit的优先权子字段(已忽略),4bit的TOS子字段和1bit未用位但必须置0.
- 4bit的Tos分别代表,最小时延,最大吞吐量,最高可靠性和最小费用。
- 4bit只能置其中1bit.
Telnet和Rlogin这两个交互应用要求最小的传输时延,因为人们主要用它们来传输少量的
交互数据 - 总长度字段(16位)
- 总长度字段是指整个IP数据包的长度 。由于该字段长16bit,所以IP数据包长度可达65535。当数据包本分片时,该字段的值也随着变化。利用首部长度字段和总长度字段,就可以知道 I P数据报中数据内容的起始位置和长度。
- 标识字段
- 唯一地标识主机发送的每一份数据报。通常每发送一份报文它的值就会加1
- TTL(time-to-live)
- 生存时间字段设置了数据包可以经过的最多路由器数。它指定了数据包的生存时间。TTL初始值由源主机设置(通常为32或64),一旦经过一个处理它的路由器,它的值就减去1。当该字段的值为0时,数据包就被丢弃,并发送ICMP报文通知 源主机。
- 协议字段
- 用来对数据报进行分用。根据它可以识别是哪个协议向 IP传送数据。
- 首部检验和字段
- 首部检验和字段是根据 I P首部计算的检验和码。它不对首部后面的数据进行计算。 ICMP、IGMP、 UDP和TCP在它们各自的首部中均含有同时覆盖首部和数据检验和码。
为了计算一份数据报的 I P检验和,首先把检验和字段置为 0。然后,对首部中每个 16 bit 进行二进制反码求和(整个首部看成是由一串 16 bit的字组成) ,结果存在检验和字段中。当收到一份 I P数据报后,同样对首部中每个 16 bit进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该为全1。如果结果不是全 1(即检验和错误),那么I P就丢弃收到的
数据报。但是不生成差错报文,由上层去发现丢失的数据报并进行重传。ICMP、IGMP、 UDP和TCP都采用相同的检验和算法
- 每一份 IP数据报都包含源 IP地址和目的 IP地址
-
IP 路由选择
- 从概念上说, I P路由选择是简单的,特别对于主机来说。如果目的主机与源主机直接相连(如点对点链路)或都在一个共享网络上(以太网或令牌环网),那么I P数据报就直接送到目的主机上。否则,主机把数据报发往一默认的路由器上,由路由器来转发该数据报。大多数的主机都是采用这种简单机制
- I P层在内存中有一个路由表。当收到一份数据报并进行发送时,它都要对该表搜索一次。当数据报来自某个网络接口时, I P首先检查目的I P地址是否为本机的 I P地址之一或者I P广播地址。如果确实是这样,数据报就被送到由 I P首部协议字段所指定的协议模块进行处理。
- 如果数据报的目的不是这些地址,那么(1)如果 I P层被设置为路由器的功能,那么就对数据报进行转发
(也就是说,像下面对待发出的数据报一样处理);否则(2)数据报被丢弃。- 目的I P地址。它既可以是一个完整的主机地址,也可以是一个网络地址,由该表目中的标志字段来指定(如下所述)。主机地址有一个非0的主机号(见图1 - 5),以指定某一特定的主机,而网络地址中的主机号为0,以指定网络中的所有主机(如以太网,令牌环网)。
- 下一站(或下一跳)路由器( next-hop router)的I P地址,或者有直接连接的网络 I P地址。下一站路由器是指一个在直接相连网络上的路由器,通过它可以转发数据报。下一站路由器不是最终的目的,但是它可以把传送给它的数据报转发到最终目的。
- 标志。其中一个标志指明目的 I P地址是网络地址还是主机地址,另一个标志指明下一站路由器是否为真正的下一站路由器,还是一个直接相连的接口(我们将在 9 . 2节中详细介绍这些标志) 。
- 为数据报的传输指定一个网络接口。
- I P路由选择是逐跳地( hop - by - hop)进行的。从这个路由表信息可以看出, IP并不知道到达任何目的的完整路径(当然,除了那些与主机直接相连的目的)。所有的IP路由选择只为数据报传输提供下一站路由器的 IP地址。它假定下一站路由器比发送数据报的主机更接近目的,而且下一站路由器与该主机是直接相连的。
- I P路由选择主要完成以下这些功能
- 搜索路由表,寻找能与目的 I P地址完全匹配的表目(网络号和主机号都要匹配)。如果找到,则把报文发送给该表目指定的下一站路由器或直接连接的网络接口(取决于标志字段的值)。
- 搜索路由表,寻找能与目的网络号相匹配的表目。如果找到,则把报文发送给该表目指定的下一站路由器或直接连接的网络接口(取决于标志字段的值)。
- 搜索路由表,寻找标为“默认( d e f a u l t)”的表目。如果找到,则把报文发送给该表目指定的下一站路由器。
*为一个网络指定一个路由器,而不必为每个主机指定一个路由器,这是 I P路由选择机制的另一个基本特性。这样做可以极大地缩小路由表的规模,比如 Internet上的路由器有只有几千个表目,而不会是超过 100万个表目
第11章 UDP:用户数据包协议
引言
- UDP是一个简单的面向数据报的运输层协议:进程的每个输出操作都正好产生一个 UDP数据报,并组装成一份待发送的IP数据报
- 应用程序必须关心 IP数据报的长度。如果它超过网络的 MTU,那么就要对IP数据报进行分片。如果需要,源端到目的端之间的每个网络都要进行分片,并不只是发送端主机连接第一个网络才这样做
UDP首部
- 端口号表示发送进程和接收进程
- UDP长度字段指的是UDP首部和UDP数据的字节长度
- 该字段的最小值为 8字节(发送一份0字节的UDP数据报是OK)
- 这个UDP长度是有冗余的。 IP数据报长度指的是数据报全长(图3 - 1),因此UDP数据报长度是全长减去IP首部的长度
- UDP检验和
- UDP检验和覆盖UDP首部和UDP数据。回想IP首部的检验和,它只覆盖IP的首部 — 并不覆盖IP数据报中的任何数据。
- UDP和TCP在首部中都有覆盖它们首部和数据的检验和。 UDP的检验和是可选的,而TCP的检验和是必需的
- 尽管U D P检验和的基本计算方法与我们在 3 . 2节中描述的 I P首部检验和计算方法相类似(16 bit字的二进制反码和),但是它们之间存在不同的地方。
- 首先, UDP数据报的长度可以为奇数字节,但是检验和算法是把若干个 16 bit字相加。解决方法是必要时在最后增加填充字节0,这只是为了检验和的计算(也就是说,可能增加的填充字节不被传送)**
- 其次,UDP数据报和TCP段都包含一个1 2字节长的伪首部,它是为了计算检验和而设置的。伪首部包含 IP首部一些字段。其目的是让 UDP两次检查数据是否已经正确到达目的地
IP分片
-
物理网络层一般要限制每次发送数据帧的最大长度,任何时候I P层接收到一份要发送的 I P数据报时,它要判断向本地哪个接口发送数据(选路),并查询该接口获得其MTU。IP把MTU与数据报长度进行比较,如果需要则进行分片。分片可以发生在原始发送端主机上,也可以发生在中间路由器上
-
把一份IP数据报分片以后,只有到达目的地才进行重新组装
-
重新组装由目的端的IP层来完成,其目的是使分片和重新组装过程对运输层( TCP和UDP)是透明的,
-
除了某些可能的越级操作外。已经分片过的数据报有可能会再次进行分片(可能不止一次)。IP首部中包含的数据为分片和重新组装提供了足够的信息
-
当IP数据报被分片后,每一片都成为一个分组,具有自己的 I P首部,并在选择路由时与其他分组独立。这样,当数据报的这些片到达目的端时有可能会失序,但是在 IP首部中有足够的信息让接收端能正确组装这些数据报片
-
下面这些字段用于分片过程
- 标识字段
- 对于发送端发送的每份IP数据报来说,其标识字段都包含一个唯一值。该值在数据报分片时被复制到每个片中
- 标志字段
- 标志字段用其中一个比特来表示“更多的片”。除了最后一片外,其他每个组成数据报的片都要把该比特置 1
- 标志字段中有一个比特称作“不分片”位。如果将这一比特置 1,IP将不对数据报进行分片
- 片偏移字段
- 片偏移字段指的是该片偏移原始数据报开始处的位置。另外,当数据报被分片后,每个片的总长度值要改为该片的长度值
- 标识字段
-
尽管I P分片过程看起来是透明的,但有一点让人不想使用它:即使只丢失一片数据也要重传整个数据报。为什么会发生这种情况呢?因为 I P层本身没有超时重传的机制——由更高层来负责超时和重传(T C P有超时和重传机制,但U D P没有。一些UDP应用程序本身也执行超时和重传)。当来自TCP报文段的某一片丢失后,TCP在超时后会重发整个TCP报文段,该报文段对应于一份IP数据报。没有办法只重传数据报中的一个数据报片。事实上,如果对数据报分片的
是中间路由器,而不是起始端系统,那么起始端系统就无法知道数据报是如何被分片的 -
使用UDP很容易导致IP分片(在后面我们将看到,TCP试图避免分片,但对于应用程序来说几乎不可能强迫 TCP发送一个需要进行分片的长报文段)
一个分片的例子
-
假定 IP首部为20字节,UDP首部为8字节。我们分别以数据长度为1471, 1472, 1473和1 4 7 4字节运行sock程序。最后两次应该发生分片
-
但是对应于写1473字节的I P数据报长度为1501,就必须进行分片(第3行和第4行)。同理,写1474字节产生的数据报长度为1502,它也需要进行分片(第5行和第6行)。
-
IP首部的标识字段
- 首先,frag 26304(第3行和第4行)和frag 26313 (第5行和第6行)指的是IP首部中标识字段的值
-
UDP长度字段
- 分片信息中的下一个数字,即第 3行中位于冒号和@号之间的1480,是除IP首部外的片长
在分片时,除最后一片外,其他每一片中的数据部分(除 IP首部外的其余部分)必须是 8字节的整数倍
- 分片信息中的下一个数字,即第 3行中位于冒号和@号之间的1480,是除IP首部外的片长
-
片偏移字段
- 位于@符号后的数字是从数据报开始处计算的片偏移值。
- 两份数据报第1片的偏移值均为0(第3行和第5行),第2片的偏移值为1480(第4行和第6行)
-
任何运输层首部只出现在第1片数据中,所以其他分片是没有UDP首部,也就是没有端口号
-
术语解释
- IP数据报是指IP层端到端的传输单元(在分片之前和重新组装之后),分组是指在IP层和链路层之间传送的数据单元。一个分组可以是一个完整的 IP数据报,也可以是IP数据报的一个分片。
ICMP不可达差错(需要分片)
- 发生ICMP不可达差错的另一种情况是,当路由器收到一份需要分片的数据报,而在 IP首部又设置了不分片(DF)的标志比特。如果某个程序需要判断到达目的端的路途中最小 MTU是多少 — 称作路径MTU发现机制(2 . 9节),那么这个差错就可以被该程序使用
用Traceroute确定路径MTU
- 要做的是发送分组,并设置“不分片”标志比特。发送的第一个分组的长度正好与出口 MTU相等,每次收到ICMP“不能分片”差错时(在上一节讨论的)就减小分组的长度。
最大UDP数据报长度
- 理论上,IP数据报的最大长度是65535字节,这是由IP首部(图3 - 1)16比特总长度字段所限制的。去除20字节的IP首部和8个字节的UDP首部,UDP数据报中用户数据的最长长度为65507字节。
- 如果接收到的数据报长度大于应用程序所能处理的长度,那么会发生什么情况呢?不幸的是,该问题的答案取决于编程接口和实现
- 在讨论TCP时,我们发现它为应用程序提供连续的字节流,而没有任何信息边界。 TCP以应用程序读操作时所要求的长度来传送数据,因此,在这个接口下,不会发生数据丢失。
UDP输入队列
- 通常程序所使用的每个 UDP端口都与一个有限大小的输入队列相联系。这意味着,来自不同客户的差不多同时到达的请求将由 UDP自动排队。接收到的 UDP数据报以其接收顺序交给应用程序(在应用程序要求交送下一个数据报时)
- 然而,排队溢出造成内核中的 UDP模块丢弃数据报的可能性是存在的。
第12章 广播和多播
引言
- 有三种 IP地址:单播地址、广播地址和多播地址
- 广播和多播仅应用于 UDP
第17章 TCP:传输控制协议
TCP提供一种面向连接的,可靠的字节流服务
- 面向连接意味着两个使用 TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个 TCP连接
- TCP通过下列方式体用可靠性
- 应用数据被分割成TCP认为最适合发送的数据块,由 TCP传递给IP的信息单位称为报文段或段
- 当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。(超时及重传策略)。
- 当TCP收到发自TCP连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒。
- TCP将保持它首部和数据的检验和
- 既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此 TCP报文段的到达也可能会失序。如果必要, TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。
- 既然IP数据报会发生重复,TCP的接收端必须丢弃重复的数据。
- TCP还能提供流量控制 TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。
- 两个应用程序通过T C P连接交换8 bit字节构成的字节流。T C P不在字节流中插入记录标识符。我们将这称为字节流服务(byte stream service)应用程序对数据的发送和接收是没有边界限制的 。
TCP的首部
TCP数据被封装在一个IP数据包中
-
TCP包首部
-
-
源端口和目的端口
- 每个TCP段都包含源端和目的端的端口号,用于寻找发端和收端应用进程。这两个值加上IP首部中的源端I P地址和目的端IP地址唯一确定一个T C P连接
-
序号和确认号
- 序号用来标识从TCP发端向TCP收端发送的数据字节流,它表示在这个报文段中的的第一个字节的序号。TCP用序号对每个字节进行计数。
- 当建立一个新的连接时, SYN标志变1。序号字段包含由这个主机选择的该连接的初始序号ISN(Initial Sequence Number)。该主机要发送数据的第一个字节序号为这个 ISN加1,因为SYN标志消耗了一个序号(将在下章详细介绍如何建立和终止连接,届时我们将看到 F I N标志也要占用一个序号)
- 既然每个传输的字节都被计数,确认序号包含发送确认的一端所期望收到的下一个序号。因此,确认序号应当是上次已成功收到数据字节序号加 1。只有ACK标志(下面介绍)为 1时确认序号字段才有效。
- TCP为应用层提供全双工服务。这意味数据能在两个方向上独立地进行传输。因此,连接的每一端必须保持每个方向上的传输数据序号。
- 我们说TCP缺少选择确认是因为 T C P首部中的确认序号表示发方已成功收到字节,但还不包含确认序号所指的字节。当前还无法对数据流中选定的部分进行确认。例如,如果1~1024字节已经成功收到,下一报文段中包含序号从 20 49~3072的字节,收端并不能确认这个新的报文段。它所能做的就是发回一个确认序号为 1025的ACK。它也无法对一个报文段进行否认。例如,如果收到包含 1025~2048字节的报文段,但它的检验和错, TCP接收端所能做的就是发回一个确认序号为 1025的ACK
-
4位首部长度
- 首部长度给出首部中32 bit字的数目。需要这个值是因为任选字段的长度是可变的。这个字段占4 bit,因此TCP最多有6 0字节的首部。然而,没有任选字段,正常的长度是 2 0字节。
-
6位保留位
-
6位标志位
- 在TCP首部中有6个标志比特。它们中的多个可同时被设置为 1
- URG 紧急指针(u rgent pointer)有效(见20.8节)。
- ACK 确认序号有效。
- PSH 接收方应该尽快将这个报文段交给应用层。
- RST 重建连接。
- SYN 同步序号用来发起一个连接。这个标志和下一个标志将在第 1 8章介绍。
- FIN 发端完成发送任务。
- 在TCP首部中有6个标志比特。它们中的多个可同时被设置为 1
-
16位窗口大小
- TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个 16 bit字段,因而窗口大小最大为 65535字节。
-
16位检验和
- 检验和覆盖了整个的T C P报文段:T C P首部和T C P数据。这是一个强制性的字段,一定是由发端计算和存储,并由收端进行验证
-
16位紧急指针
- 只有当URG标志置1时紧急指针才有效。紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号
-
可选字段
- 最长报文大小,又称为 MSS (Maximum Segment Size)。每个连接方通常都在通信的第一个报文段(为建立连接而设置 SYN标志的那个段)中指明这个选项 。
-
TCP将用户数据打包构成报文段;它发送数据后启动一个定时器;另一端对收到的数据进行确认,对失序的数据重新排序,丢弃重复数据; TCP提供端到端的流量控制,并计算和验证一个强制性的端到端检验和。
第18章 TCP连接的建立与终止
TCP三次握手抓包分析
发送端 | 标志位 | seq | ack | 数据长度 | 状态 |
---|---|---|---|---|---|
C | SYN | 2330448289 | 0 | 0 | SYN_SENT |
S | SYN,ACK | 982412518 | 2330448290 | 0 | SYN_RCVD |
C | ACK | 2330448290 | 982412519 | 0 | ESTABLISHED |
S收到ACK之后也会成为ESTABLISHED状态
- tls
发送端 | 标志位 | seq | ack | 数据长度 |
---|---|---|---|---|
C | Client hello | 2330448290 | 982412519 | 134 |
S | ACK,PSH | 982412519 | 2330448424 | |
S | Server hello | 982412519 | 2330448424 | 1460 |
C | ACK | 2330448424 | 982413979 |
- 建立一个连接需要三次握手,而终止一个连接要经过 4次握手。这由T C P的半关闭(half - close)造成的。既然一个TCP连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭。这原则就是当一方完成它的数据发送任务后就能发送一个 FIN来终止这个方向连接。当一端收到一个 FIN,它必须通知应用层另一端几经终止了那个方向的数据传送。发送FIN通常是应用层进行关闭的结果。
- 收到一个FIN只意味着在这一方向上没有数据流动。一个 TCP连接在收到一个F I N后仍能发送数据。而这对利用半关闭的应用来说是可能的,尽管在实际应用中只有很少的 TCP应用程序这样做.
TCP四次挥手抓包分析
发送端 | 标志位 | seq | ack | 状态 |
---|---|---|---|---|
C | FIN,ACK | 3514992616 | 218767418 | ESTABLISHED, FIN_WAIT_1 |
S | ACK | 218767418 | 3514992617 | CLOSE_WAIT FIN_WAIT_2 |
S | FIN,ACK | 218767418 | 3514992617 | LAST_ACK ,TIME_WAIT |
C | ACK | 3514992617 | 218767419 | CLOSE |
为什么是三次握手四次挥手
-
三次握手可以防止已经失效的连接请求报文突然又传输到服务器端导致的服务器资源浪费
-
资源浪费观点:引自《计算机网络》释疑与习题解答 谢希仁
- 如果只有两次握手,当客户端的SYN请求连接在网络管道中阻塞,客户端没有接收到ACK报文,就会重新发送SYN,由于没有第三次握手,服务器不清楚客户端是否收到了自己发送的建立连接的ACK确认信号,所以每收到一个SYN就只能主动建立一个连接,这会造成什么情况呢?如果客户端的SYN阻塞了,重复发送多次SYN报文,那么服务器在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费。即两次握手会造成消息滞留情况下,服务器重复接受无用的连接请求SYN报文,而造成重复分配资源。
-
可靠性论断:
- 另外一种是 如果想确定双通道通畅,必须使用三个包的发送接收,也就是三次握手:“这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的. 请注意这里的本质需求,信道不可靠, 数据传输要可靠. 三次达到了, 那后面你想接着握手也好, 发数据也好, 跟进行可靠信息传输的需求就没关系了. 因此,如果信道是可靠的, 即无论什么时候发出消息, 对方一定能收到, 或者你不关心是否要保证对方收到你的消息, 那就能像UDP那样直接发送消息就可以了.”三次是保证双方互相明确对方能收能发的最低值。理论上讲不论握手多少次都不能确认一条信道是“可靠”的,但通过3次握手可以至少确认它是“可用”的,再往上加握手次数不过是提高“它是可用的”这个结论的可信程度。另外Tcp的可靠传输更多的是靠重传机制来保证的
-
初始序列号
- 三次握手的本质是为了同步双方的初始序列号:
- 为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。TCP建立连接的握手,实质上就是建立一个双向的可靠通信连接,一边一个来回,每一边都自带超时重传来确保可靠性(而不是靠握手的次数)。TCP的3次握手是优化的结果,其实它应该是4次握手,由于是从零开始的建立连接,因此将SYN的ACK以及被动打开的SYN合并成了一个SYN-ACK。握手的作用,旨在确定两个双向的初始序列号,TCP用序列号来编址传输的字节,由于是两个方向的连接,所以需要两个序列号,握手过程不传输任何字节,仅仅确定初始序列号。
-
最大报文长度
- 最大报文段长度(MSS)表示TCP传往另一端的最大块数据的长度。当一个连接建立时,连接的双方都要通告各自的 MSS.
- 如果一方不接收来自另一方的 MSS值,则MSS就定为默认值536字节(这个默认值允许20字节的IP首部和20字节的TCP首部以适合576字节I P数据报
- 当 TCP发送一个SYN时,或者是因为一个本地应用进程想发起一个连接,或者是因为另一端的主机收到了一个连接请求,它能将 MSS值设置为外出接口上的 MTU长度减去固定的I P首部和T C P首部长度。对于一个以太网,MSS值可达1460字节。
-
TCP半关闭
- TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。这就是所谓的半关闭
2MSL等待状态
- TIME_WAIT状态也称为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment Lifetime),它是任何报文段被丢弃前在网络内的最长时间。我们知道这个时间是有限的,因为 TCP报文段以IP数据报在网络内传输,而IP数据报则有限制其生存时间的TTL字段。
- 对一个具体实现所给定的 MSL值,处理的原则是:当 TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为 2倍的MSL。这样可让TCP再次发送最后的A C K以防这个ACK丢失(另一端超时并重发最后的FIN)
- 这种2MSL等待的另一个结果是这个 TCP连接在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的 IP地址和端口号)不能再被使用。这个连接只能在 2MSL结束后才能再被使用。
- 在连接处于2MSL等待时,任何迟到的报文段将被丢弃。因为处于 2 MSL等待的、由该插口对(socket pair)定义的连接在这段时间内不能被再用,因此当要建立一个有效的连接时,来自该连接的一个较早替身( incarnation)的迟到报文段作为新连接的一部分不可能不被曲解(一个连接由一个插口对来定义。一个连接的新的实例( instance)称为该连接的替身)
- 客户执行主动关闭并进入 TIME_WAIT是正常的。服务器通常执行被动关闭,不会进入TIME_ WAIT状态。这暗示如果我们终止一个客户程序,并立即重新启动这个客户程序,则这个新客户程序将不能重用相同的本地端口。
TIME_WAIT状态存在的理由:
-
尽最大努力可靠地实现TCP全双工连接的终止
- 在进行关闭连接四次挥手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,服务器将重发最终的FIN,因此客户端必须维护状态信息允许它重发最终的ACK。如果不维持这个状态信息,那么客户端将响应RST分节,服务器将此分节解释成一个错误因而,要实现TCP全双工连接的正常终止,必须处理终止序列四个分节中任何一个分节的丢失情况,主动关闭的客户端必须维持状态信息进入TIME_WAIT状态。
-
允许老的重复分节在网络中消逝
- TCP分节可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个原来的迷途分节就称为lost duplicate。
- 在关闭一个TCP连接后,马上又重新建立起一个相同的IP地址和端口之间的TCP连接,后一个连接被称为前一个连接的化身(incarnation),那么有可能出现这种情况,前一个连接的迷途重复分组在前一个连接终止后出现,从而被误解成从属于新的化身。为了避免这个情况,TCP不允许处于TIME_WAIT状态的连接启动一个新的化身,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时候,来自连接先前化身的重复分组已经在网络中消逝。
平静时间的概念
- 对于来自某个连接的较早替身的迟到报文段, 2MSL等待可防止将它解释成使用相同插口对的新连接的一部分。但这只有在处于 2 MSL等待连接中的主机处于正常工作状态时才有效。如果使用处于2 MSL等待端口的主机出现故障,它会在 MSL秒内重新启动,并立即使用故障前仍处于2 M S L的插口对来建立一个新的连接吗?如果是这样,在故障前从这个连接发出而迟到的报文段会被错误地当作属于重启后新连接的报文段。无论如何选择重启后新连接的初始序号,都会发生这种情况。为了防止这种情况,RFC 793指出TCP在重启动后的MSL秒内不能建立任何连接。这就称为平静时间(quiet time)。
异常终止
-
异常终止一个连接对应用程序来说有两个优点:(1)丢弃任何待发数据并立即发送复位报文段;(2)RST的接收方会区分另一端执行的是异常关闭还是正常关闭。应用程序使用的API必须提供产生异常关闭而不是正常关闭的手段。
-
一个TCP连接由一个4元组唯一确定:本地 IP地址、本地端口号、远端 IP地址和远端端口号。
第19章 TCP的交互数据流
- 引言
- 一些有关TCP通信量的研究如[Caceres et al. 1991]发现,如果按照分组数量计算,约有一半的TCP报文段包含成块数据(如 FTP、电子邮件和 Usenet新闻),另一半则包含交互数据(如Telnet和Rlogin)。如果按字节计算,则成块数据与交互数据的比例约为 90 %和10 %。这是因为成块数据的报文段基本上都是满长度( full - sized)的(通常为512字节的用户数据),而交互数据则小得多。
经受时延的确认
- 通常TCP在接收到数据时并不立即发送ACK;相反,它推迟发送,以便将 ACK与需要沿该方向发送的数据一起发送(有时称这种现象为数据捎带ACK)。绝大多数实现采用的时延为 200 ms,也就是说,TCP将以最大200 ms的时延等待是否有数据一起发送。
Nagle算法
- 该算法要求一个 TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组的确认到达之前不能发送其他的小分组。相反, TCP收集这些少量的分组,并在确认到来时以一个分组的方式发出去。该算法的优越之处在于它是自适应的:确认到达得越快,数据也就发送得越快。
小结
- 交互数据总是以小于最大报文段长度的分组发送,接收方使用经受时延的确认方法来判断确认是否可被推迟发送,
以便与回送数据一起发送。
第20章 TCP的成块数据流
引言
- 本章我们将介绍 TCP所使用的被称为滑动窗口协议的另一种形式的流量控制方法。该协议允许发送方在停止并等待确认前可以连续发送多个分组。由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输
正常数据流
- 报文段7的A C K的序号之所以是2048而不是3073是由以下原因造成的:当一个分组到达时,它首先被设备中断例程进行处理,然后放置到 IP的输入队列中。三个报文段 4、5和6依次到达并按接收顺序放到 I P的输入队列。I P将按同样顺序将它们交给 TCP。当TCP处理报文段4时,该连接被标记为产生一个经受时延的确认。 T C P处理下一报文段(5),由于TCP现在有两个未完成的报文段需要确认,因此产生一个序号为 2048的A C K(报文段7),并清除该连接产生经受时延的确认标志。 TCP处理下一个报文段( 6),而连接又被标志为产生一个经受时延的确认。在报文段9到来之前,由于时延定时器溢出,因此产生一个序号为 3073的ACK(报文段8)。报文段8中的窗口大小为3072表明在TCP的接收缓存中还有1024个字节的数据等待被应用程序读取
- 通常使用的“隔一个报文段确认”的策略
- 注意到报文段7、14和1 6中的ACK确认了两个收到的报文段是很重要的。使用 TCP的滑动窗口协议时,接收方不必确认每一个收到的分组。在 TCP中,ACK是累积的 — 它们表示接收方已经正确收到了一直到确认序号减 1的所有字节
- 发送方发送4个背靠背(back-to-back)的数据报文段去填充接收方的窗口,然后停下来等待一个ACK。接收方发送ACK(报文段8),但通告其窗口大小为 0,这说明接收方已收到所有数据,但这些数据都在接收方的 TCP缓冲区,因为应用程序还没有机会读取这些数据。另一个ACK(称为窗口更新)在17.4 ms后发送,表明接收方现在可以接收另外的 4096个字节的数据。虽然这看起来像一个 ACK,但由于它并不确认任何新数据,只是用来增加窗口的右边沿,因此被称为窗口更新。
滑动窗口
- 滑动窗口示意图
- 我们知道窗口大小是与确认序号相对应的。发送方计算它的可用窗口,该窗口表明多少数据可以立即被发送。
- 当接收方确认数据后,这个滑动窗口不时地向右移动。窗口两个边沿的相对运动增加或减少了窗口的大小。我们使用三个术语来描述窗口左右边沿的运动:
- 称窗口左边沿向右边沿靠近为窗口合拢。这种现象发生在数据被发送和确认时。
- 当窗口右边沿向右移动时将允许发送更多的数据,我们称之为窗口张开。这种现象发生在另一端的接收进程读取已经确认的数据并释放了 TCP的接收缓存时
- 当右边沿向左移动时,我们称之为窗口收缩。 Host Requirements RFC强烈建议不要使用这种方式。但TCP必须能够在某一端产生这种情况时进行处理。第 2 2 . 3节给出了这样的一个例子,一端希望向左移动右边沿来收缩窗口,但没能够这样做。
- 因为窗口的左边沿受另一端发送的确认序号的控制,因此不可能向左边移动。如果接收到一个指示窗口左边沿向左移动的 ACK,则它被认为是一个重复 ACK,并被丢弃。
- 如果左边沿到达右边沿,则称其为一个零窗口,此时发送方不能够发送任何数据。
- 以该图为例可以总结如下几点:
- 发送方不必发送一个全窗口大小的数据。
- 来自接收方的一个报文段确认数据并把窗口向右边滑动。这是因为窗口的大小是相对于确认序号的。
- 正如从报文段7到报文段8中变化的那样,窗口的大小可以减小,但是窗口的右边沿却不能够向左移动
- 接收方在发送一个A C K前不必等待窗口被填满。在前面我们看到许多实现每收到两个报文段就会发送一个ACK。
窗口大小
PUSH标志
- 发送方使用该标志通知接收方将所收到的数据全部提交给接收进程
慢启动(slow start)
- 该算法通过观察到新分组进入网络的速率应该与另一端返回确认的速率相同而进行工作
- 慢启动为发送方的TCP增加了另一个窗口:拥塞窗口(congestion window),记为cwnd。
- 当与另一个网络的主机建立 TCP连接时,拥塞窗口被初始化为 1个报文段(即另一端通告的报文
段大小)。每收到一个ACK,拥塞窗口就增加一个报文段( cwnd以字节为单位,但是慢启动以报文段大小为单位进行增加) - 发送方取拥塞窗口与通告窗口中的最小值作为发送上限。
- 拥塞窗口是发送方使用的流量控制,而通告窗口则是接收方使用的流量控制
发送方开始时发送一个报文段,然后等待 ACK。当收到该ACK时,拥塞窗口从1增加为2,即可以发送两个报文段。当收到这两个报文段的 ACK时,拥塞窗口就增加为4。这是一种指数增加的关系
- 当与另一个网络的主机建立 TCP连接时,拥塞窗口被初始化为 1个报文段(即另一端通告的报文
带宽时延乘积
- 可以计算通道的容量为:capacity (bit) = bandwidth (b/s) × round-trip time (s)
拥塞
- 当数据到达一个大的管道(如一个快速局域网)并向一个较小的管道(如一个较慢的广域网)发送时便会发生拥塞
- 当多个输入流到达一个路由器,而路由器的输出流小于这些输入流的总和时也会发生拥塞。
小结
- 正如我们在本章一开始时讲的那样,没有一种单一的方法可以使用 TCP进行成块数据的交换。这是一个依赖于许多因素的动态处理过程,有些因素我们可以控制(如发送和接收缓存的大小),而另一些我们则没有办法控制(如网络拥塞、与实现有关的特性等)。在本章,我们已经考察了许多TCP的传输过程,介绍了所有我们能够看到的特点和算法
- 进行成块数据有效传输的最重要的方法是 TCP的滑动窗口协议
第21章 TCP的超时与重传
- TCP提供可靠的运输层。它使用的方法之一就是确认从另一端收到的数据。但数据和确认都有可能会丢失。 T C P通过在发送时设置一个定时器来解决这种问题。如果当定时器溢出时还没有收到确认,它就重传该数据。对任何实现而言,关键之处就在于超时和重传的策略,即怎样决定超时间隔和如何确定重传的频率
- 对每个连接,TCP管理4个不同的定时器。
- 重传定时器使用于当希望收到另一端的确认。在本章我们将详细讨论这个定时器以及一些相关的问题,如拥塞避免。
- 坚持( persist)定时器使窗口大小信息保持不断流动,即使另一端关闭了其接收窗口。第22章将讨论这个问题
- 保活( keepalive )定时器可检测到一个空闲连接的另一端何时崩溃或重启。第 23章将描述这个定时器
- 2MSL定时器测量一个连接处于 TIME_ WAIT状态的时间
- 超时与重传的简单例子
- 现在检查连续重传之间不同的时间差,它们取整后分别为 1、3、6、12、24、48和多个64秒。在本章的后面,我们将看到当第一次发送后所设置的超时时间实际上为 1.5秒(它在首次发送后的1.0136秒而不是精确的1 . 5秒后,发生的原因我们已在图 18-7中进行了解释),此后该时间在每次重传时增加1倍并直至64秒。这个倍乘关系被称为“指数退避 (exponential backoff )”
- 首次分组传输与复位信号传输之间的时间差约为9分钟,该时间在目前的T C P实现中是不可变的。
往返时间测量
- TCP超时与重传中最重要的部分就是对一个给定连接的往返时间( RTT)的测量
- 首先TCP必须测量在发送一个带有特别序号的字节和接收到包含该字节的确认之间的RTT
慢启动
- 连接上最初只允许传输一个报文段,然后在发送下一个报文段之前必须等待接收它的确认。当报文段2被接收后,就可以再发送两个报文段。上一章介绍了慢启动算法。
拥塞避免算法
- 拥塞避免算法是一种处理丢失分组的方法
- 拥塞避免算法和慢启动算法是两个目的不同、独立的算法。但是当拥塞发生时,我们希望降低分组进入网络的传输速率,于是可以调用慢启动来作到这一点。在实际中这两个算法通常在一起实现
- *拥塞避免算法和慢启动算法需要对每个连接维持两个变量:一个拥塞窗口 cwnd和一个慢启动门限ssthresh。
- 对一个给定的连接,初始化cwnd为1个报文段,ssthresh为65535个字节。
- TCP输出例程的输出不能超过 cwnd和接收方通告窗口的大小。
- 拥塞避免是发送方使用的流量控制,而通告窗口则是接收方进行的流量控制。前者是发送方感受到的网络拥塞的估
计,而后者则与接收方在该连接上的可用缓存大小有关。 - 拥塞发生时(超时或收到重复确认),ssthresh被设置为当前窗口大小的一半( cwnd和接收方通告窗口大小的最小值,但最少为 2个报文段)。此外,如果是超时引起了拥塞,则cwnd被设置为1个报文段(这就是慢启动)。
- 当新的数据被对方确认时,就增加 cwnd,但增加的方法依赖于我们是否正在进行慢启动或拥塞避免。如果 cwnd小于或等于ssthresh,则正在进行慢启动,否则正在进行拥塞避免。慢启动一直持续到我们回到当拥塞发生时所处位置的半时候才停止(因为我们记录了在步骤 2中给我们制造麻烦的窗口大小的一半),然后转为执行拥塞避免
拥塞避免算法要求每次收到一个确认时将 cwnd增加1 /cwnd。与慢启动的指数增加比起来,这是一种加性增长(additive increase)。
快速重传与快速恢复算法
- 我们认识到在收到一个失序的报文段时, TCP立即需要产生一个 ACK(一个重复的A C K)。这个重复的ACK不应该被迟延。该重复的 ACK的目的在于让对方知道收到一个失序的报文段,并告诉对方自己希望收到的序号.
- 由于我们不知道一个重复的 A C K是由一个丢失的报文段引起的,还是由于仅仅出现了几个报文段的重新排序,因此我们等待少量重复的 ACK到来。假如这只是一些报文段的重新排序,则在重新排序的报文段被处理并产生一个新的 ACK之前,只可能产生1 ~ 2个重复的ACK。如果一连串收到 3个或3个以上的重复ACK,就非常可能是一个报文段丢失了)。于是我们就重传丢失的数据报文段,而无需等待超时定时器溢出。这就是快速重传算法。接下来执行的不是慢启动算法而是拥塞避免算法。这就是快速恢复算法。
- 在这种情况下没有执行慢启动的原因是由于收到重复的 A C K不仅仅告诉我们一个分组丢失了。由于接收方只有在收到另一个报文段时才会产生重复的 A C K,而该报文段已经离开了网络并进入了接收方的缓存。也就是说,在收发两端之间仍然有流动的数据,而我们不想执行慢启动来突然减少数据流。
- 这个算法通常按如下过程进行实现:
- 收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口 cwnd的一半。重传丢失的报文段。设置cwnd为ssthresh加上3倍的报文段大小。
- 每次收到另一个重复的 ACK时,cwnd增加1个报文段大小并发送 1个分组(如果新的cwnd允许发送)
但是在接收到重复 ACK的过程中cwnd允许保持增加,这是因为每个重复的ACK表示1个报文段已离开了网络
- 下一个确认新数据的ACK到达时,设置cwnd = ssthresh。这个ACK应该是在进行重传后的一个往返时间内对步骤 1中重传的确认。另外,这个 ACK也应该是对丢失的分组和收到的第 1个重复的ACK之间的所有中间报文段的确认。这一步采用的是拥塞避免,因为当分组丢失时我们将当前的速率减半。
重新分组
- 当TCP超时并重传时,它不一定要重传同样的报文段
小结
- 本章提供了对TCP超时和重传机制的详细研究。使用的第 1个例子是一个丢失的建立连接的SYN,并观察了在随后的重传和超时中怎样使用指数退避方式
- 慢启动、拥塞避免、快速重传和快速恢复
第22章 TCP的坚持定时器
引言
- TCP必须能够处理打开此窗口的 ACK丢失的情况。ACK的传输并不可靠,也就是说, TCP不对ACK报文段进行确认, TCP只确认那些包含有数据的ACK报文段。
- 如果一个确认丢失了,则双方就有可能因为等待对方而使连接终止:接收方等待接收数据(因为它已经向发送方通告了一个非 0的窗口),而发送方在等待允许它继续发送数据的窗口更新。为防止这种死锁情况的发生。发送方使用一个坚持定时器 (persist timer)来周期性地向接收方查询,以便发现窗口是否已增大。这些从发送方发出的报文段称为窗口探查 ( window probe )
一个例子
- 报文段13中,服务器确认了前面 4个数据报文段,然后通告窗口为 0,从而使客户停止发送任何其他的数据。这就引起客户设置其坚持定时器。如果在该定时器时间到时客户还没有接收到一个窗口更新,它就探查这个空的窗口以决定窗口更新是否丢失。由于服务器进程处于休眠状态,所以TCP缓存9216字节的数据并等待应用进程读取。
- 计算坚持定时器时使用了普通的 TCP指数退避
- 窗口探查包含一个字节的数据(序号为 9217)。TCP总是允许在关闭连接前发送一个字节的数据。请注意,尽管如此,所返回的窗口为 0的ACK并不是确认该字节(它们确认了包括9216在内的所有数据),因此这个字节被持续重传
- 坚持状态与第21章中介绍的重传超时之间一个不同的特点就是 TCP从不放弃发送窗口探查。这些探查每隔 6 0秒发送一次,这个过程将持续到或者窗口被打开,或者应用进程使用的连接被终止。
糊涂窗口综合症
-
基于窗口的流量控制方案,如 TCP所使用的,会导致一种被称为“糊涂窗口综合症 SWS(Silly Window Syndrome)”的状况。
-
该现象可发生在两端中的任何一端:接收方可以通告一个小的窗口(而不是一直等到有大的窗口时才通告),而发送方也可以发送少量的数据(而不是等待其他的数据以便发送一个大的报文段)。可以在任何一端采取措施避免出现糊涂窗口综合症的现象
- 接收方不通告小窗口。通常的算法是接收方不通告一个比当前窗口大的窗口(可以为0),除非窗口可以增加一个报文段大小(也就是将要接收的 MSS)或者可以增加接收方缓存空间的一半,不论实际有多少。
- 发送方避免出现糊涂窗口综合症的措施是只有以下条件之一满足时才发送数据:
- 可以发送一个满长度的报文段;
- 可以发送至少是接收方通告窗口大小一半的报文段;
- 可以发送任何数据并且不希望接收 ACK(也就是说,我们没有还未被确认的数据)或者该连接上不能使用Nagle算法(见第1 9.4节)。
-
一个糊涂窗口例子
-
-
- 前4个数据报文段及其A C K(报文段1 ~ 5)表示发送方正在填充接收方的缓存。在那个时刻发送方停止了发送,但仍然有更多的数据需要发送。它将自己的坚持定时器置为最小值 5分钟。当坚持定时器时间到时,就发送出 1个字节的数据(报文段 6)。接收的应用进程已经从接收缓存中读取了2 5 6字节的数据(在时刻3.99),因此这个字节被接受并被确认(报文段 7段)。但是通告窗口仍为0,由于接收方仍然没有足够的空间来接收一个满长度的报文,或者不能腾出缓存空间的一半。这就是接收方的糊涂窗口避免措施
- 发送方的坚持定时器被复位,并在5秒后再次到时(在时刻10. 151)。然后又发送一个字节并被确认(报文段8和9),而接收方的缓存空间还不够用(1022字节),使得通告窗口为0。
- 发送方的坚持定时器在时刻 15. 151再次时间到,又发送了另一个字节并被确认(报文段10和11)。这一次由于接收方有 1533字节的有效缓存空间,因此通告了一个非 0窗口。发送方立即利用这个窗口发送了1024字节的数据(报文段12)。对这1024字节数据的确认(报文段13)通告其窗口为509字节。这看起来与我们在前面看到的小窗口通告相抵触。
- 在这里之所以发生这种情况,是因为报文段 11段通告了一个大小为 1533字节的窗口,而发送方只使用了其中的1024字节。如果在报文段13中的A C K通告其窗口为0,就会违反窗口的右边沿不能向左边沿移动而导致窗口收缩的 TCP原则(见第20.3节)
- 接下来我们看到发送方没有立即向这个小窗口发送数据。这就是发送方采取的糊涂窗口避免策略。相反,它等待另一个坚持定时器在时刻 20.151到时间,并在该时刻发送 509字节的数据。尽管它最终还是发送了一个长度为 509字节的小数据段,但在发送前它等待了 5秒钟,看是否会有一个ACK到达,以便可以将窗口开得更大。这 509字节的数据使得接收缓存仅剩下768字节的有效空间,因此接收方通告窗口为 0(报文段15)。
小结
- 连接的一方需要发送数据但对方已通告窗口大小为0时,就需要设置TCP的坚持定时器。发送方使用与第2 1章类似的重传间隔时间,不断地探查已关闭的窗口。这个探查过程将一直持续下去。
- 当运行一个例子来观察坚持定时器时,我们还观察到了 TCP的避免出现糊涂窗口综合症的现象。这就是使 TCP避免通告小的窗口大小或发送小的报文段。在我们的例子中,可以观察到发送方和接收方为避免糊涂窗口综合症所使用的策略
第23章 TCP的保活定时器
引言
- 一个服务器希望知道客户主机是否崩溃并关机或者崩溃又重新启动。许多实现提供的保活定时器可以提供这种能力
- 保活定时器是一个有争论的功能。许多人认为如果需要,这个功能不应该在 TCP中提供,而应该由应用程序来完成。这是应当认真对待的一些问题之一,因为在这个论题上有些人表达出了很大的热情。
- 保活功能主要是为服务器应用程序提供的。服务器应用程序希望知道客户主机是否崩溃,从而可以代表客户使用资源
描述
- 如果一个给定的连接在两个小时之内没有任何动作,则服务器就向客户发送一个探查报文段
- 客户主机依然正常运行,并从服务器可达。客户的 TCP响应正常,而服务器也知道对方是正常工作的。服务器在两小时以后将保活定时器复位。如果在两个小时定时器到时间之前有应用程序的通信量通过此连接,则定时器在交换数据后的未来 2小时再复位。
- 客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的 TCP都没有响应。服务器将不能够收到对探查的响应,并在 75秒后超时。服务器总共发送 10个这样的探查,每个间隔 7 5秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。
- 客户主机崩溃并已经重新启动。这时服务器将收到一个对其保活探查的响应,但是这个响应是一个复位,使得服务器终止这个连接。
- 客户主机正常运行,但是从服务器不可达。这与状态 2相同,因为TCP不能够区分状态4与状态2之间的区别,它所能发现的就是没有收到探查的响应
- 第1种情况下,服务器的应用程序没有感觉到保活探查的发生。 TCP层负责一切。这个过程对应用程序都是透明的,直至第 2、3或4种情况发生。在这三种情况下,服务器应用程序将收到来自它的 TCP的差错报告(通常服务器已经向网络发出了读操作请求,然后等待来自客户的数据。
第24章 TCP的未来和性能
- 路径MTU
- 长肥管道 具有大的带宽时延乘积的网络被称为长肥网络。使用长肥管道会遇到多种问题。
- TCP首部中窗口大小为 16 bit,从而将窗口限制在 65535个字节内。但是从图 2 4 - 5的最后一列可以看到,现有的网络需要一个更大的窗口来提供最大的吞吐量
- TCP对每个字节数据使用一个32 bit无符号的序号来进行标识。如果在网络中有一个被延迟一段时间的报文段,它所在的连接已被释放,而一个新的连接在这两个主机之间又建立了,怎样才能防止这样的报文段再次出现呢?