1. 应用层概述

运输层是整个网络体系结构中的关键层次之一。一定要弄清楚以下一些重要概念:
(1)运输层为相互通信的应用层进程提供逻辑通信
(2)端口和套接字的意义
(3)无连接的UDP的特点
(4)面向连接的TCP的特点
(5)在不可靠的网络上实现可靠传输的工作原理,停止等待协议和ARQ协议
(6)TCP滑动窗口、流量控制、拥塞控制和连接管理

  • 计算机网络体系结构中的物理层、数据链路层以及网络层它们共同解决了将主机通过异构网络互联所面临的问题,实现了主机到主机的通信。
  • 但实际上在计算机网络中进行通信的真正实体是位于通信两端主机中的进程。
  • 如何为运行在不同主机上的应用进程提供直接的通信服务是运输层的任务,运输层协议又称为端到端协议。

从计算机网络体系结构的角度看运输层:
image.png

image.png

小结
image.png

2. 运输层端口号、复用与分用的概念

端口号

image.png

发送方的复用和接收方的分用

注意:全双工通信的双方既是发送方也是接收方。这里,我们就将左边的应用进程叫做发送方,右边的叫做接收方
image.png

  • 复用是指发送方不同的应用进程都可以使用同一个运输层协议传输数据(当然需要加上适当的首部)。
  • 分用是指接收方的运输层在剥去报文的首部后能够把这些数据正确交付目的应用进程。

    TCP/IP体系的应用层常用协议所使用的运输层熟知端口号

    image.png

3. 运输层的两个主要协议

  • 用户数据报协议UDP(User Datagram Protocol)
  • 传输控制协议TCP(Transmission Control Protocol)

image.png

UDP协议

概述

用户数据报协议UDP只是在IP的数据报服务之上增加了很少一点的功能,这就是复用和分用的功能以及差错检测的功能。

主要特点

  1. UDP是无连接的,即发送数据之前不需要建立连接(当然,发送结束后也没有连接可释放),因此减少了开销和发送数据之前的时延。
  2. UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表(这里面有许多参数)。
  3. UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。UDP对应用程序交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。接收方的UDP,对IP层交上来的UDP用户数据报,在去除首部后就原封不动地交付上层的应用进程。
  4. UDP没有拥塞控制,因此网络出现地拥塞不会使源主机地发送速率降低。
  5. UDP支持一对一、一对多、多对一和多对多的交互通信。
  6. UDP的首部开销小,只有8个字节。

    结构

    image.png

    首部格式

    用户数据报UDP有两个字段:首部字段和数据字段。首部字段很简单,只有8个字节,由4个字段组成,每个字段的长度都是两个字节。各字段意义如下:

  7. 源端口:源端口号。在需要对方回信时选用。不需要时可用全0

  8. 目的端口:目的端口号。这在终点交付报文时必须使用。
  9. 长度:UDP用户数据报的长度,其最小值是8(仅有首部)
  10. 检验和:检测UDP用户数据报在传输过程中是否有错。有错就丢弃。

TCP协议

主要特点

  1. TCP是面向连接的运输层协议。也就是说,应用程序在使用TCP协议之前,必须先建立TCP连接。在传输完数据完毕后,必须释放已经建立的TCP连接。
  2. 每一条TCP连接只能有两个端点(endpoint),每一条TCP连接只能是点对点的(一对一)。
  3. TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复,并且按序到达。
  4. TCP提供全双工通信。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向发送的数据。
  5. 面向字节流。TCP中的“流”(stream)指的是流入到进程或从进程流出的字节序列。虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅仅看成是一连串的无结构的字节流。

    结构

    image.png

    TCP的连接

  • TCP把连接作为最基本的抽象。

前面已经说过,每一条TCP连接有两个端点。那么,这两个端点究竟是什么呢?
不是主机,不是主机的IP地址,不是应用进程,也不是运输层的协议端口。TCP连接的端点叫做套接字插口

  • 端口号拼接到IP地址即构成了套接字。
  • 套接字 socket = (IP 地址:端口号)

每一条TCP连接唯一地被通信两端的两个端点(即两个套接字)所确定。

UDP与TCP的对比

image.png

  • UDP的通信是无连接的,不需要套接字(Socket),TCP是面向连接的,TCP之间的通信必须要在两个套接字(Socket)之间建立连接。
  • UDP 传送的数据单位协议是 UDP 报文用户数据报。TCP 传送的数据单位协议是 TCP 报文段(segment)。

4. 可靠传输的工作原理

我们知道,TCP发送的报文段是交给IP层传送的,而TCP下面的网络所提供的是不可靠的传输。因此,TCP只有采取适当的措施才能使得两个运输层之间的通信变得可靠。
理想的传输条件有以下两个特点:

  • 传输信道不产生差错
  • 不管发送方以多快得速度发送数据

虽然实际的网络都不具备以上两个理想条件,但我们可以使用一些可靠传输协议,当出现差错时,让发送方重传出现差错的数据;同时在接收方来不及处理收到的数据时,及时告诉发送方降低发送数据的速度。这样一来,就能够实现可靠传输了。下面从最简单的停止等待协议讲起。

4.1 停止等待协议

这里讨论的是可靠传输的原理,因此把传送的数据单元都称为分组

  • “停止等待”就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。
  1. 无差错情况,如图(a)

第五章 运输层 - 图11

  1. 出现差错,如图(b)

这里可能是B接收M1检测出了差错,就丢弃M1,其他什么也不做;也可能是M1在传输过程中丢失了,这时B什么也不知道。这两种情况下,B都不会发送任何消息。
超时重传:A只要超过了一段时间仍然没有收到确认,就认为刚才发送的分组丢失了,因而重传前面发送过的分组。这就叫做超时重传。要实现超时重传,就要在每发送一个分组时设置一个超时计时器。A只要在超时计时器到期之前收到了相应的确认,就撤销该超时计时器。
不过,这里要注意以下三点:
1)A在发送完一个分组后,必须暂时保留已发送的分组的副本(在发生超时重传时使用)。只有在收到相应的确认后才能清除暂时保留的分组副本。
2)分组和确认分组都必须进行编号。这样才能明确是哪一个发送出去的分组收到了确认,哪一个分组还没有收到确认。
3)超时计时器的重传时间应当比数据在分组传输的平均往返时间更长一些。

  1. 确认丢失和确认迟到

image.png

  1. 信道利用率

image.png
image.png
停止等待协议的优点是简单,但缺点是信道利用率太低。为了提高效率,发送方可以不使用低效率的停止等待协议,而是采用流水线传输
流水线传输就是发送方可连续发送多个分组,不必发完一个分组就停顿下来等待对方的确认。这样可以使信道上一直有数据不间断地在传送。这种传输方式可以获得很高的信道利用率。

4.2 连续ARQ协议

image.png
滑动窗口协议比较复杂,是TCP协议的精髓所在。
连续ARQ协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。
接收方一般都是采用累积确认的方式,不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,这表示:到这个分组为止的所有分组都已经正确收到了。

5. TCP报文段的首部格式

image.png

首部中各字段的作用

源端口和目的端口
image.png

序号、确认号和确认标志位
image.png

数据偏移、保留、窗口和校验和
image.png

同步标志位、终止标志位、复位标志位、推送标志位、紧急标志位和紧急指针
image.png

选项和填充
image.png

6. TCP可靠传输的实现

image.png

image.png

image.png

7. TCP的流量控制

  • 一般来说,我们总是希望数据传输的更快一些。
    • 但是如果发送方把数据发送得过快,接收方就可能来不及接收,这就会造成数据的丢失。
  • 所谓流量控制(flow control)就是让发送方的发送速率不要太快,要让接收方来得及接收。
  • 利用滑动窗口机制可以很方便地在TCP连接上实现对发送方的流量控制。
    • TCP接收方利用自己的接收窗口的大小来限制发送方发送窗口的大小。
    • TCP发送方收到接收方的零窗口通知后,应启动持续计时器。持续计时器超时后,向接收方发送零窗口探测报文。

利用滑动窗口实现 流量控制
举个例子:
image.png
这时主机A可以将发送缓存中序号1~200的字节数据全部删除,因为主机B已经收到了对它们的累积确认。

image.png

image.png
此时主机A可将发送缓存中序号501~600的字节数据全部删除,因为主机B已经收到了对它们的累计确认。

image.png

image.png

  • 如果零窗口探测报文在发送过程中丢失,也能打破死锁局面
  • 因为零窗口探测报文段也有重传计时器,重传计时器超时后,零窗口探测报文段会被重传

8. TCP的拥塞控制

概念

image.png

网络拥塞的影响因素

网络拥塞往往是由许多因素引起的。例如

  • 某个节点缓存的容量太小
  • 链路的容量不足
  • 处理及处理的速率太慢
  • 拥塞本身会进一步加剧拥塞

    拥塞控制的一般原理

  • 拥塞控制的前提:网络能够承受现有的网络负荷。

  • 实践证明,拥塞控制是很难设计的,因为它是一个动态问题。
  • 分组的丢失是网络发生拥塞的征兆而不是原因。
  • 在许多情况下,甚至正是拥塞控制本身成为了引起网络性能恶化、甚至发生死锁的原因。

    开环控制和闭环控制

    image.png

监测网络拥塞的指标

  1. 由于缺少缓存空间而被丢弃的分组的百分数;
  2. 平均队列长度;
  3. 超时重传的分组数;
  4. 平均分组时延;
  5. 分组时延的标准差,等等。

上述这些指标的上升都标志着拥塞的增长。

拥塞控制的算法

image.png

image.png
真正的发送窗口值 = Min (接收方窗口值,拥塞窗口值)

慢开始(slow-start)

  • 目的:用来确定网络的负载能力或拥塞程度。
  • 算法的思路:由小到大逐渐增大拥塞窗口数值。
  • 两个变量:
  • 拥塞窗口(cwnd):初始拥塞窗口值:2 种设置方法。窗口值逐渐增大。
    • 1 至 2 个最大报文段 (旧标准)
    • 2 至 4 个最大报文段 (RFC 5681)
  • 慢开始门限(ssthresh):防止拥塞窗口增长过大引起网络拥塞。

image.png
纵坐标(拥塞窗口):

  • 会随网络拥塞程度以及所使用的拥塞控制算法动态变化

横坐标(传输轮次):

  • 发送方给接收方发送数据报文段后,接收方给发送方发发回相应的确认报文段
  • 一个传输轮次所经历的时间其实就是往返时间往返时间并非是恒定的数值
  • 使用传输轮次是为了强调把拥塞窗口所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个报文段的确认

image.png
上图中swnd是发送窗口,每经过一个传输轮次,拥塞窗口就加倍,窗口大小按指数级增加,2^(n-1)。

拥塞控制(congestion avoidance)

  • 思路:让拥塞窗口 cwnd 缓慢地增大,避免出现拥塞。
  • 每经过一个传输轮次,拥塞窗口 cwnd = cwnd + 1
  • 使拥塞窗口 cwnd 按线性规律缓慢增长。
  • 在拥塞避免阶段,具有 “加法增大” (Additive Increase) 的特点。

image.png

如果在发送过程中出现部分报文段丢失,必然会造成发送方对这些丢失报文段的超时重传
image.png

cwnd值减少到1时,开始执行慢开始算法
image.png
image.png

两个算法的完整示意图:
image.png

下面介绍快重传和快恢复:
image.png

快重传(fast retransmit)

image.png

快恢复(fast recovery)

image.png

改进后算法的整体示意图:
image.png

9. TCP超时重传时间的选择

TCP采用了一种自适应算法,它记录一个报文段发出去的时间,以及收到相应确认的时间。这两个时间之差就是报文段的往返时间RTT。

image.png
如果超时重传时间RTO的值设置得比RTT0的值小很多,这会引起报文段不必要的重传,使网络负荷增大

image.png
如果超时重传时间RTO的值设置得远大于RTT0的值,这会使重传时间推迟的太长,使网络的空闲时间增大,降低传输效率

image.png
image.png

RFC6298建议使用下式计算超时重传时间RTO
image.png

往返时间RTT的测量比较复杂
image.png
image.png

TCP超时重传的计算(举个例子)
image.png

小结
image.png

10. TCP连接的建立

image.png

  • TCP 建立连接的过程叫做握手
  • 握手需要在客户和服务器之间交换三个 TCP 报文段。称之为三报文握手
  • 采用三报文握手主要是为了防止已失效的连接请求报文段突然又传送到了,因而产生错误。

TCP连接的建立主要解决以下三个问题
image.png

TCP使用“三次握手”建立连接

  • TCP 连接的建立采用客户服务器方式
  • 主动发起连接建立的应用进程叫做TCP客户 (client)。
  • 被动等待连接建立的应用进程叫做TCP服务器 (server)。

“握手”需要在TCP客户端和服务器之间交换三个TCP报文段,以下是过程

  1. 最初两者都处于关闭状态

image.png

  1. TCP服务器进程首先创建传输控制块,用来存储TCP连接中的一些重要信息。例如TCP连接表、指向发送和接收缓存的指针、指向重传队列的指针,当前的发送和接收序号等。之后,就准备接受TCP客户端进程的连接请求。

    1. 此时,TCP服务器进程就进入监听状态,等待TCP客户端进程的连接请求。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/27187548/1655170167155-82e68385-c30e-4d13-9e19-8bdfabac22b2.png#clientId=u25aeb58d-1dac-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=ud9f93542&margin=%5Bobject%20Object%5D&name=image.png&originHeight=344&originWidth=1200&originalType=url&ratio=1&rotation=0&showTitle=false&size=187375&status=done&style=none&taskId=ueed95266-c3b6-451d-8e8e-966113d1e2d&title=)
  2. TCP服务器进程是被动等待来自TCP客户端进程的连接请求,因此称为被动打开连接

image.png

  1. TCP客户进程也是首先创建传输控制块,由于TCP连接建立是由TCP客户端主动发起的,因此称为主动打开连接

image.png

  1. 然后,在打算建立TCP连接时,向TCP服务器进程发送TCP连接请求报文段,
  2. 并进入同步已发送状态
  3. TCP连接请求报文段首部中
  4. 同步位SYN被设置为1,表明这是一个TCP连接请求报文段
  5. 序号字段seq被设置了一个初始值x,作为TCP客户端进程所选择的初始序号
  6. 请注意:TCP规定SYN被设置为1的报文段不能携带数据,但要消耗掉一个序号
  1. TCP服务器进程收到TCP连接请求报文段后,如果同意建立连接,则向TCP客户进程发送TCP连接请求确认报文段,并进入同步已接收状态

image.png

  1. TCP连接请求确认报文段首部中
  2. 同步位SYN和确认为ACK都设置为1,表明这是一个TCP连接请求确认报文段
  3. 序号字段seq被设置了一个初始值y,作为TCP服务器进程所选择的初始序号,
  4. 确认号字段ack的值被设置成了x+1,这是对TCP客户进程所选择的初始序号(seq)的确认
  5. 请注意:这个报文段也不能携带数据,因为它是SYN被设置为1的报文段,但同样要消耗掉一个序号
  1. TCP客户进程收到TCP连接请求确认报文段后,还要向TCP服务器进程发送一个普通的TCP确认报文段,并进入连接已连接状态

image.png

  1. 普通的TCP确认报文段首部中
  2. 确认位ACK被设置为1,表明这是一个普通的TCP确认报文段
  3. 序号字段seq被设置为x+1,这是因为TCP客户进程发送的第一个TCP报文段的序号为x,所以TCP客户进程发送的第二个报文段的序号为x+1
  4. 确认号字段ack被设置为y+1,这是对TCP服务器进程所选择的初始序号的确认
  5. 请注意:TCP规定普通的TCP确认报文段可以携带数据,但如果不携带数据,则不消耗序号
  1. TCP服务器进程收到该确认报文段后也进入连接已建立状态

image.png
现在,TCP双方都进入了连接已建立状态,它们可以基于已建立好的TCP连接,进行可靠的数据传输。

为什么TCP客户进程最后还要发送一个普通的TCP确认报文段?能否使用“两报文握手”建立连接?
下图是“两报文握手”过程:
image.png

原因:
为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误,这种情况是:一端(client)A发出去的第一个连接请求报文并没有丢失,而是因为某些未知的原因在某个网络节点上发生滞留,导致延迟到连接释放以后的某个时间才到达另一端(server)B。
本来这是一个早已失效的报文段,但是B收到此失效的报文之后,会误认为是A再次发出的一个新的连接请求,于是B端就向A又发出确认报文,表示同意建立连接。如果不采用“三次握手”,那么只要B端发出确认报文就会认为新的连接已经建立了,但是A端并没有发出建立连接的请求,因此不会去向B端发送数据,B端没有收到数据就会一直等待,这样B端就会白白浪费掉很多资源。
所以并不多余,这是为了防止已失效的连接请求报文段突然又传送到了TCP服务器,进而导致错误。

小结
image.png

11. TCP连接的释放

TCP通过”四报文挥手“来释放连接

  • 任何一方(TCP客户或TCP服务器)都可以在数据传送结束后发出连接释放的通知

过程(假设客户端主动关闭连接)

  1. TCP客户进程的应用进程通知其主动关闭TCP连接,TCP客户进程会发送TCP连接释放报文段,并进入终止等待1状态

image.png

  1. TCP连接释放报文段首部中
  2. - 终止位FIN和确认为ACK的值都被设置为1,表明这是一个TCP连接释放报文段,同时也对之前收到的报文段进行确认
  3. - 序号seq字段的值设置为u,它等于TCP客户进程之前已传送过的数据的最后一个字节的序号加1
  4. - 确认号ack字段的值设置为v,它等于TCP客户进程之前已收到的、数据的最后一个字节的序号加1
  5. 注意:TCP规定终止位FIN等于1的报文段即使不携带数据,也要消耗掉一个序号
  1. TCP服务器进程收到TCP连接释放报文段后,会发送一个普通的TCP确认报文段并进入关闭等待状态

image.png

  1. 普通的TCP确认报文段首部中
  2. - 确认位ACK的值被设置为1,表明这是一个普通的TCP确认报文段
  3. - 序号seq字段的值设置为v,它等于TCP服务器进程之前已传送过的数据的最后一个字节的序号加1,这也与之前收到的TCP连接释放报文段中的确认号匹配
  4. - 确认号ack字段的值设置为u+1,这是对TCP连接释放报文段的确认
  1. TCP服务器进程应该通知高层应用进程,TCP客户进程要断开与自己的TCP连接,此时,从TCP客户进程到TCP服务器进程这个方向的连接就释放了

image.png

  1. 这时的TCP连接属于半关闭状态,也就是TCP客户进程已经没有数据要发送了
  2. 但如果TCP服务器进程还有数据要发送,TCP客户进程仍要接收,也就是说从TCP服务器进程到TCP客户进程这个方向的连接并未关闭
  1. TCP客户进程收到TCP确认报文段后就进入终止等待2状态,等待TCP服务器进程发出的TCP连接释放报文段

image.png

  1. 若使用TCP服务器进程的应用进程已经没有数据要发送了,应用进程就通知其TCP服务器进程释放连接
  2. 由于TCP连接释放是由TCP客户进程主动发起的,因此TCP服务器进程对TCP连接的释放称为被动关闭连接
  1. TCP服务器进程发送TCP连接释放报文段并进入最后确认状态

image.png

  1. 该报文段首部中
  2. - 终止位FIN和确认位ACK的值都被设置为1,表明这是一个TCP连接释放报文段,同时也对之前收到的报文段进行确认
  3. - 序号seq字段的值为w,这是因为在半关闭状态下,TCP服务器进程可能又发送
  4. - 确认号ack字段的值为u+1,这是对之前收到的TCP连接释放报文段的重复确认
  1. TCP客户进程收到TCP连接释放报文段后,必须针对该报文段发送普通的TCP确认报文段,之后进入时间等待状态 ``` 该报文段首部中
  • 确认为ACK的值被设置为1,表明这是一个普通的TCP确认报文段
  • 序号seq字段的值设置为u+1,这是因为TCP客户进程之前发送的TCP连接释放报文段虽然不携带数据,但要消耗掉一个序号
  • 确认号ack字段的值设置为w+1,这是对所收到的TCP连接释放报文段的确认

TCP服务器进程收到该报文段后就进入关闭状态,而TCP客户进程还要进过2MSL后才能进入关闭状态

```

问题:TCP客户进程在发送完最后一个确认报文后,为什么不直接进入关闭状态?而是要进入时间等待状态?
image.png

  • 因为时间等待状态以及处于该状态2MSL时长,可以确保TCP服务器进程可以收到最后一个TCP确认报文段而进入关闭状态
  • 另外,TCP客户进程在发送完最后一个TCP确认报文段后,在经过2MSL时长,就可以使本次连接持续时间内所产生的所有报文段都从网络中消失,这样就可以使下一个新的TCP连接中,不会出现旧连接中的报文段

TCP保活计时器的作用
假设TCP双方已经建立了连接,但是后来,TCP客户进程所在的主机突然出现了故障,导致TCP服务器进程以后就不能再收到TCP客户进程发来的数据,因此,应当有措施使TCP服务器进程不要再白白等待下去。
image.png