以下为个人学习笔记和习题整理
课程:哈尔滨工业大学 计算机网络
https://www.bilibili.com/video/BV1Up411Z7hC?share_source=copy_web

# 概述

# 本章目标

  1. 理解传输层服务的基本理论和基本机制

    • 复用 / 分用 (multiplexing and demultiplexing):传输层的 核心功能 ,扩展网络层的消息投递服务。

      Extending the network layer’s delivery service between two end systems to a delivery service between two application-layer processes running on the end systems.

    • 可靠数据传输 (reliable data transfer) 机制:两个通信实体如何通过 不可靠的信道 (存在数据丢失或损坏) 进行可靠数据传输。
    • 拥塞控制 (congestion control) 机制:控制传输层实体的 传输速率 ,以避免拥塞,或者从拥塞中恢复。
  2. 掌握 Internet 的传输层协议

    • UDP : 不可靠的无连接的传输服务
    • TCP : 可靠的面向连接的传输服务

# 传输层服务概述

  1. 传输层协议为运行在 不同主机上(end-to-end)进程 提供了一种 逻辑通信机制 ,由此应用程序可以不必知道底层物理基础设施进行数据传输的细节。

    逻辑连接 :从应用程序的视角,两个运行进程的主机之间仿佛是直接连接的,不关心物理距离、途径多少路由器等。

    Untitled_0

    传输层协议 “驻留”(live in) 在 端系统 中:传输层实现 应用层的消息网络边缘(即网络层) 的信息交付(反之亦然),而不关心消息如何在 网络核心 中移动。如图所示,中间的路由器 (routers) 只有三层协议栈,其并不关心传输层所附加的信息。

  2. 端系统运行传输层协议

    • 发送方 (sender):将应用递交的 message(消息) 分成一个或多个的 segment(报文段) ,并向下传给网络层

      如何实现的?

      • This is done by (possibly) breaking the application messages into smaller chunks and adding a transport-layer header to each chunk to create the transport-layer segment.
    • 接收方 (receiver):将接受到的 segment 组装成 message ,并向上交给应用层
  3. 传输层可以为应用提供多种协议,提供不同的 服务模型(service nodel)

    • 如 Internet 中,传输层可以向应用层提供 TCPUDP 两种传输层协议

# 传输层和网络层之间的关系

  • 网络层:提供 主机 之间的逻辑通信机制
  • 传输层:提供 应用进程 之间的逻辑通信机制
    1. 位于网络层之上依赖于网络层服务
      • 传输层能提供的服务,受到网络层服务模型限制,如 时延保障带宽保障
        (如网络层没有提供,则传输层亦无法提供)
    2. 对网络层服务进行(可能的)增强
      • 某些网络层不提供的服务,能够由传输层来提供,如 可靠传输加密

    一个 主机 上运行有多个 应用进程

# Internet 上的传输层协议

  1. 可靠按序的交付服务 TCP
    (可靠:不出错,不丢失。按序:按发送顺序送达。)

    • 拥塞控制 (congestion control)
    • 流量控制 (flow control)
    • 连接建立
  2. 不可靠的交付服务 UDP

    • 基于 “尽力而为(best-effort)” 的网络层协议 IP 协议 (不可靠) ,没有做 可靠性 方面的扩展

      UDP 只提供传输层 最基本 的服务,即

      • 实现多路复用和解复用 (multiplexing and demultiplexing):通过 端口号(port number) 实现
      • 差错检测 (error checking):通过 校验和(checksum) 实现

# 多路复用与解复用

何时考虑 多路复用解复用

  • Although we have introduced multiplexing and demultiplexing in the context of the Internet transport protocols , it’s important to realize that they are concerns whenever a single protocol at one layer (at the transport layer or elsewhere) is used by multiple protocols at the next higher layer.
  • 如果某层的 一个协议 对应直接上层的 多个协议或实体 ,则需要多路复用 / 分用。
  • 对于 Internet 而言,
    • TCP 协议 需要为多个使用 TCP 服务的 应用进程 交付信息,此时需要传输层将接收到的信息交付给 正确的 (appropriate) 应用进程。
    • 网络层仅有 IP 协议 ,而传输层有 UDPTCP 2 种协议,故需复用 / 分用。

# 传输层多路复用和解复用

一个应用程序 进程 可以拥有 1个或多个 套接字,因此,接收方的传输层 不直接 把数据交给进程,而是交给中间的 套接字

  • 在任意时刻, 接收方的主机 上存在着多个套接字,每个套接字有一个独一无二的 标识符(identifier)
  • 标识符的 格式 取决于该套接字是 TCP 套接字 还是 UDP 套接字(★)

如图所示:

Untitled_1

  • 发送端进行多路复用:从 多个 socket 接受数据,为每块数据封装上 头部信息 ,生成 segment ,交给网络层。

    The job of gathering data chunks at the source host from different sockets , encapsulating each data chunk with header information (that will later be used in demultiplexing) to create segments , and passing the segments to the network layer is called multiplexing.

  • 接收端进行多路分用:传输层依据 头部信息 ,将 segment 中的数据交给 正确的 socket ,即不同的应用进程。

    This job of delivering the data in a transport-layer segment to the correct socket is called demultiplexing.

# 多路复用的实现

由以上讨论可知,传输层实现多路复用需要:

  1. 每个 socket 有独一无二的 标识符 (在主机中即 端口号 )。

  2. 每个 segment 有指明特定 socket 的特殊 字段(fields) ,如图所示,为 源端口号目的端口号
    (传输层报文段所共有的,除此之外, TCPUDP 还有其他的字段)

    Untitled_2

    Each port number is a 16-bit number, ranging from 0 to 65535 . The port numbers ranging from 0 to 1023 are called well-known port numbers and are restricted, which means that they are reserved for use by well-known application protocols such as HTTP (which uses port number 80) and FTP (which uses port number 21).

具体实现:

  • Each socket in the host could be assigned a port number , and when a segment arrives at the host, the transport layer examines the destination port number in the segment and directs the segment to the corresponding socket. The segment’s data then passes through the socket into the attached process.
  • As we’ll see, this is basically how UDP does it. (★)
    However, we’ll also see that multiplexing / demultiplexing in TCP is yet more subtle.

# 无连接分用(面向 UDP 协议)

UDP 多路复用和解复用过程:

Untitled_3

  1. 多路复用:发送方的传输层创建 UDP 报文段 ,其中包含 应用层数据源端口号目的端口号 、以及 两个其他的值 (介绍 UDP 报文段时会提及,现在不重要),并将其交给网络层进行传输。
  2. 多路分用:接收方的传输层通过网络层收到 UDP 报文段 (此时 目的 IP 的作用已经达到),检查段中的 目的端口号 ,然后将 UDP 段递交给绑定该目的端口号的 socket

一个 UDP socket 完全由一个 二元组目的 IP目的端口号)标识。

  • 因此,如果两个 UDP 报文段拥有 不同的源 IP 地址 和 / 或 不同的源端口号 ,但是却有相同的 目的 IP目的端口号 ,则他们将会 通过同一个 socket 被递交给同一个进程。

另外,如图 Figure 3.4 所示,报文段中 源端口号 的作用是作为 返回地址 的一部分(另一部分是 源 IP 地址 )。

# 面向连接的分用(TCP 连接)

# TCP socket

Untitled_4

与 UDP socket 不同,一个 TCP socket 由一个 四元组 标识: 源 IP 地址 / 源端口号目的 IP 地址 / 目的端口号

  • 因此,当一个 TCP 报文段从网络到达主机时,主机使用 所有的这四个值 来将该报文段定向(解复用)到相应的 socket。
  • 特别的,与 UDP 不同,如果两个 TCP 报文段拥有 不同的源 IP 地址不同的源端口号 ,则他们会定向到 两个不同的 socket
    (存在例外:该 TCP 报文段携带的是初始的 连接建立请求 (connection-establishment request),如下例中 监听 特定端口的 TCP Server)
  1. 再来看看 Web server 是怎么使用 端口号 的。

    实际上,当客户端(浏览器)向服务器发送报文段时,无论是初始的 请求建立连接 的报文段还是 携带 HTTP 请求 的报文段,都以 80 作为目的端口号,如前所述,服务器通过 源 IP 地址源端口号 来区分不同的客户端。

  2. 另外,图中的 TCP server 为 每个 TCP 连接 创建了一个 进程 ,每个进程有自己的 连接套接字

    事实上,当今的高性能服务器通常只使用 一个进程 ,而为每个连接创建一个新的 线程 (带有新的 连接套接字 )。因此,该服务器在任意时刻都可能有(具有不同标识符的) 许多连接套接字 连接到同一个的进程。

# TCP 连接建立

回顾之前 Section 2.7.2 的 TCP client-server 套接字编程示例:

  • The TCP server application has a “welcoming socket” , that waits for connection-establishment requests from TCP clients on port number 12000 .

  • The TCP client creates a socket and sends a connection establishment request segment with the lines:

    clientSocket = socket(AF_INET, SOCK_STREAM)
    clientSocket.connect((serverName,12000))

    (通过 connect() 函数发送一个请求建立连接的报文段

  • A connection-establishment request is nothing more than a TCP segment with destination port number 12000 and a special connection-establishment bit set in the TCP header (discussed in Section 3.5). The segment also includes a source port number that was chosen by the client.
    (The struct of connection-request segment

  • When the host operating system of the computer running the server process receives the incoming connection-request segment with destination port 12000, it locates the server process (★) that is waiting to accept a connection on port number 12000. The server process then creates a new socket :

    connectionSocket, addr = serverSocket.accept()

    操作系统 收到请求建立连接的报文段后,将其定向到 监听 该报文段目标端口号的 进程

  • Also, the transport layer at the server notes the following four values in the connection-request segment:

    1. the source port number in the segment,
    2. the IP address of the source host,
    3. the destination port number in the segment, and
    4. its own IP address.

    The newly created connection socket is identified by these four values (★); all subsequently arriving segments whose source port, source IP address, destination port, and destination IP address match these four values will be demultiplexed to this socket . With the TCP connection now in place, the client and server can now send data to each other.

    • 新的 连接套接字(connection socket) 是由该 四元组 所标识的。
    • 后续的 TCP 报文段 都将由段中的四元组定向到相应的 socket

    注:TCP 连接是 一对一 的。

# 无连接传输:UDP

引言:假如你对设计一个 只提供必要服务(no-frills)最基本(bare-bones) 的传输层协议感兴趣,你将打算怎么做呢?

# 概述

如前所述, UDP 基本上基于 IP 协议 ,没有做太多的扩展,它

  • 只是做了传输协议能做的 最少工作多路复用/分用 ,以及简单的 差错检测(error checking) ,除此之外不做任何事。
  • 基本上将 网络层服务 “暴露” 给了应用层,应用程序几乎是直接与 IP 打交道,因此也相对 轻量(lightweight)
  • 基于 IP 协议,也提供 “尽力而为(best-effort)” 的服务,即 UDP 段可能 丢失 ,也可能 乱序
  • 无连接 服务,UDP 发送方 / 接收方之间 不需要握手 ,每个 UDP 段的处理独立于其他段。
  1. 为什么 应用开发者 会选择 UDP ?而 TCP 提供可靠传输,不总是更好吗?

    • UDP 没有拥塞控制,可以更好地控制发送时间 / 速率

      应用进程 一旦将数据传给 UDP ,UDP 将数据封装后 立即 将报文段传给网络层。另一方面, TCP 提供拥塞控制机制,当拥塞发生时会 限制发送方 的发送速率。同时为了实现 可靠传输 ,TCP 在报文段被确认接受之前会不断地 重传报文段 ,无论花费多少时间。

      • 因为 实时应用(real-time) 通常对 最小发送速率 有要求,不希望过分地延迟报文段的传输,并且能容忍一定的丢失, TCP 的服务模型不是特别符合应用的需求,可以使用 UDP 实现。
    • 无需建立连接,减少延迟
      TCP 在开始数据传输前会进行 三次握手 。而 UDP 不需要任何准备即可进行数据传输,因此不会引入建立连接的时延。
      • 这可能是 DNS 运行在 UDP 之上而不是 TCP 之上的主要原因:如果运行在 TCP 之上,则 DNS 会 慢得多
      • HTTP 使用 TCP 而不是 UDP,因为 可靠性 对于包含文本的 Web 网页 来说是至关重要的。

        但正如之前所讨论的,HTTP 中的 TCP 连接建立时延 对于 下载 Web 文档的时延 来说是一个重要的贡献因素。确实如此,谷歌的 Chrome 浏览器 使用 QUIC 协议(Quick UDP Internet Connection) ,该协议使用 UDP 作为其底层的传输协议,并在 UDP 之上的 应用层协议 上实现 可靠性

    • 实现简单,无需维护连接状态
      TCP 需要在 端系统 中维护连接状态(缓冲区参数),以实现可靠传输和拥塞控制,而 UDP 不需要。
      • 因此,对于专用于特定应用程序的服务器来说,如果该应用运行在 UDP 之上,那么相比 TCP ,它可以为 更多的 活跃客户端提供服务。
    • 头部开销少:每个 TCP 报文段有 20 bytes 的头部开销,而每个 UDP 报文段只有 8 bytes 的头部开销。
  2. 补充说明

    • 正如我们在第 2 章中所学的, 早期版本 (HTTP/1.1, HTTP/2) 的 HTTP 运行在 TCP 之上,但是 更近期版本 (HTTP/3) 的 HTTP 则运行在 UDP 之上,并在 应用层 上实现自己的差错控制和拥塞控制。
    • UDP 也用于携带 网络管理数据 (Network managment data) (SNMP),在这种情况下 UDP 相比 TCP 更合适,因为 网络管理应用程序 经常在网络处于 紧张状态 时必须运行(精确地说,在可靠的、带拥塞控制的数据传输难以实现时)。
    • 虽然 多媒体应用 通常运行在 UDP 之上,但这样做是有争议的。UDP 中缺乏 拥塞控制 ,可能导致 UDP 发送方 / 接收方之间的 高丢失率 (high lose rates) 以及 TCP 会话的挤出 (crowding out) (链路拥塞,导致 TCP 减缓其发送速率)。
    • 使用 UDP 的应用程序是可以实现 可靠数据传输 的,这可以通过在 应用程序自身 中建立 可靠性 机制来完成。

      Nevertheless, ­building reliability directly into the application allows the application to “have its cake and eat it too.”

      • That is, application processes can communicate reliably without being subjected to the transmission-rate constraints imposed by TCP’s congestion-control mechanism.
      • 在应用程序中构建 可靠传输 ,同时 避开 TCP 拥塞控制强加的 速率限制

# UDP 报文段结构

Untitled_5

  • 数据字段 (data filed):由 应用层数据 填充。
  • UDP 报头 (UDP header):由 4 个字段组成,每个字段由 2 bytes 组成。
    1. 源端口号目的端口号 :用于接收端 解复用 和作为 返回地址的一部分
    2. 长度字段 (Length) :指示了 UDP 报文段中的 字节数UDP header + UDP data)。

      由于不同报文段之间 数据字段 的大小可能不同,需要一个 明确的 长度值。

    3. 校验和字段 (Checksum) :被 接收方 用来检测 错误是否被引入 到报文段中。

      实际上,除了 UDP 报文段 外, IP 头部 中的 几个字段 也会被用于计算校验和。

# 校验和(checksum)

UDP 校验和用于 差错检测 ,即确定 UDP 报文段中的 比特 在传输过程中是否发生了 改变 (例如,由于 链路中的噪声 或者存储在 路由器 中时引入问题)。校验和的计算和使用:

  1. UDP 发送方将报文段中的所有 16 比特字(16-bit words)和(sum) 进行 反码运算(one's complement) ,求和时遇到的 任何溢出 都被 回卷(wrapped around)

    UDP at the sender side performs the 1s complement of the sum of all the 16-bit words in the segment, with any overflow encountered during the sum being wrapped around .

    计算得到的结果被放在 UDP 报文段的 校验和字段 中。
  2. 在 UDP 接收方,将 所有的16比特字 (包括 校验和 ) 加在一起,(★)
    • 如果得到的结果为 全1 ,则说明该分组中 没有差错 被引入。
    • 如果得到的结果中的 比特之一为 0 ,那么我们就知道该分组中 已经出现了差错

    尽管 UDP 提供 差错检测 ,但它不做任何 差错恢复 (实际上也 无能为力 )。


为什么要在 传输层 进行差错检测?许多 链路层协议 (包括流行的 以太网协议 (Ethernet protocol) )不也提供了差错检测?

  • 不能保证 源和目的之间的 所有链路 都提供了差错检测。
  • 当数据报存储在 路由器的内存 中时,也有可能 引入比特差错

Given that neither link-by-link reliability nor in-memory error detection is guaranteed, UDP must provide error detection at the transport layer , on an end-end basis (★), if the end-end data transfer service is to provide error detection.

这是一个在系统设计中被颂为 端到端原则 (end-end principle) 的例子,该原则指出:

  • Since certain functionality (error detection, in this case) must be implemented on an end-end basis : “functions placed at the lower levels may be redundant or of little value when compared to the cost of providing them at the higher level .”

因为 IP 是被假定为可以运行在几乎任何第 2 层协议 (layer-2 protocol) 之上的(亦即 链路层协议 可能不提供差错检测),在 传输层 提供 差错检测 以作为 安全措施 是很有用的。

# 可靠数据传输原理

三个机制实现可靠数据传输:

  • 确认(acknowledgment)ACKsequence number ,双方传输的报文段的顺序。
    若发生乱序则被暂存在 TCP buffer ,丢失报文重传后和后续报文一起投递到应用层。
  • 重传(retransmission) :对 丢包 的唯一 处理方法 ,确保交付。
  • 计时器(timeout) :用于 判定丢包 ,超时后重传。多次超时将导致连接被中断。

# 带流水线的可靠数据传输协议

# Go-Back-N(GBN)

# Selective Repeat(SR)

# 面向连接的传输:TCP

# TCP 连接

# TCP 报文段结构

# 可靠数据传输

# 流量控制

# TCP 连接管理

# 拥塞控制原理

# TCP 拥塞控制