计算机网络(九) 传输层
IP 层负责主机和主机之间的通信,但仅仅如此还不足以被实际使用,原因是主机上还有很多不同的进程,进程希望能向目标主机上具体的进程传输数据,而不是笼统地直接以主机为目标发送数据。运输层就是提供了端到端的传输服务,通信的两端就是两个主机的进程。此外,传输层还提供了差异化的传输服务(如 TCP 和 UDP。TCP 提供了数据传播的可靠性,而 UDP 延续了 ip 的 best-effort 特性,只注重快捷)
端口
端口是传输层定义的规范,由一个 16 位整数进行编号,某一类传输层协议(TCP、UDP)最多可以有 65535 个端口。
如果主机是一栋公寓,公寓里每一个进程就是一个房间,IP 地址是楼号,端口就是门牌号。
公认端口 Well-Known Ports
类似于 0.0.0.0 这类特殊的 ip 地址,公认端口是被世界共同接受、用于常用、重要的服务。如:
80 —— HTTP 端口
25 —— FTP 端口
443 —— HTTPS 端口
注册端口 Registered Ports
大型公司的软件使用的已经注册的端口,如 MySQL 的 3306。
动态端口 Dynamic Ports
除上面两种端口以外的接口,可以被应用或者用户自由使用。
套接字
套接字是传输层为应用层开放的接口,它是程序实际使用网络时中最常用的接口。
套接字接口的实现通常由操作系统内核提供。不同的操作系统内核使用的套接字接口定义以及对它的实现不同,例如,许多类 Unix 操作系统(如 Linux、macOS 和 BSD 系统)遵循 POSIX 标准。这意味着在这些系统中,套接字接口定义和实现是相似的。Windows 系统提供的套接字接口称为 Winsock。尽管它也实现了套接字的基本功能,但与 POSIX 套接字的接口存在一些差异。
流式套接字 SOCK_STREAM
基于 TCP(以及 TCP 派生的传输层协议)工作的套接字实现,提供可靠的数据传输,传输数据时需要进行连接。
数据报套接字 SOCK_DGRAM
基于 UDP(以及 UDP 派生的传输层协议)工作的套接字实现,传输数据时无需进行连接。
原始套接字 SOCK_RAW
工作在 IP 层的服务,用于一些特殊的应用,如网络安全应用需要对所有抵达主机的 ip 数据报进行筛选。这种套接字允许直接对 IP 层的网络包进行处理。
UDP 协议
UDP 协议对应用层交付的数据直接加上 UDP 头部后就交付给 IP。UDP 不会主动对数据进行分段。
UDP 报文头部
- 8 字节的 UDP 首部
- 2 字节源端口
- 2 字节目的端口
- 2 字节报文长度,单位为字节,最大为 65535 字节。
- 2 字节 UDP 校验
首部固定长度为 8 字节。其中,UDP 校验码是基于伪首部和数据部计算得到的互联网校验和。伪首部的定义如下:
- 12 字节的伪首部
- 源 IP 地址 4 字节
- 目的 IP 地址 4 字节
- 保留字段 1 字节,值为 0x0
- 协议类型 1 字节,对于 UDP,值为 0x11
- 长度,与首部的报文长度相同。
伪首部并不实际出现在报文首部,仅用于计算校验和。
可靠传输协议
停止等待 ARQ 协议
自动重传请求 (ARQ, Automatic Repeat reQuest) 协议是一种错误控制协议。它的基本思想是在数据传输过程中,接收方需要向发送方回复确认信息,发送方根据是否接收到确认信息判断数据是否发送失败。
ARQ 能够处理数据丢失和错误。如果发送方发送数据后一定时间内没有收到 ACK,则判定数据丢失,触发重传。如果连续收到 ACK ,则认为数据发送错误,触发重传。另一方面,如果接收方通过检错机制发现数据出错,则不发送 ACK 等待发送方重传(或者连续发送 ACK 触发快速重传)。
ACK 本身也可能在传输中丢失,导致数据传输重复。因此,ARQ 协议规定,需要为报文段进行编号,如果发现编号重复,则删除之。
停止-等待
是一种流量控制技术:每次数据段发送后,需要等待接收方发送确认帧(ACK),然后才继续发送下一个数据段,以此来确保数据不会发送过快。
停止等待 ARQ 的信道利用率
在使用停止-等待 ARQ 协议的情况下,信道利用率的定义是数据发送时间(发送时延)在一次完整发送周期(从开始发送到完成接收 ACK 帧的周期)中占用的比例。设 t_s 是数据发送时间(数据长度 / 带宽),RTT 是数据往返时长,信道利用率 p 的定义式如下:
分子和分母同时乘以带宽,得到:
连续 ARQ 协议 (GBN 协议)
现代互联网信道可靠性已经很高,而且带宽也越来越大。根据上文的信道利用率定义式,带宽越大,信道利用率越低,传统 ARQ 协议的效率太低了。信道可靠性较高的情况下,可以适当牺牲重传的代价换取常态的信道利用率提高。
Go-Back-N (GBN) ARQ 是一种连续 ARQ 协议,它允许发送方在得到确认之前连续发送多个数据包。具体实现细节如下:
- 发送方维护一个大小为 N 的窗口,称为发送窗口。窗口大小 N 决定了发送方可以连续发送多少个数据段,而无需等待确认。
- 发送方维护一个窗口边界 base,窗口范围即 [base, base+N]
- 接收方维护一个大小为 1 的接收窗口,每当窗口内接受到的数据段接收完成,窗口向前移动,否则丢弃。乱序帧因为不在窗口内,会被直接丢弃。
- 接收方可以择机返回 ACK(不需要为每个段返回 ACK),譬如,收到了序号为 1~5 的数据段,可以只返回 ACK 5。
- 发送方接收到 ACK M,就将 base 调整为 M + 1,如果此时发送窗口内所有数据都没有发送过,则直接发送新的数据,否则继续等待新的 ACK。
- 发送方每次发送数据后重置定时器,如果超时,则重传发送窗口内所有数据段。
- 如果接收方收到误码帧,序号 X,则发送 ACK (X-1),等待重传。
正常状态下 GBN 的运行图示:
丢包后的重传演示 (图中有个小错,接收窗口外的数据帧不会回复 ACK):
连续 ARQ 协议的信道利用率
如果每个数据段都返回 ACK,则在理想情况下,GBN 协议的信道利用率为:
其中 n 为发送窗口大小。
在累计确认的情况下,理想情况下 GBN 的信道利用率为:
选择重传协议 SR
选择重传协议是对连续 ARQ 协议的改进。有如下几点不同:
- 接收窗口可以大于 1,但小于等于发送窗口。
- 发送窗口 base 不随 ACK 移动,而是指向第一个未确认的数据帧。
- 发送方可以仅重传出错或超时的数据帧,而不是整个窗口重传。
- 接收窗口和发送窗口一般小于等于数据帧最大序号的一半。这是为了确保发送的数据帧序号横跨两个序号周期时,不会互相混淆。
正常状态下 SR 的运行过程:
存在丢包时,SR 的运行过程:
TCP 协议
TCP 协议规定数据传输的双方维护一个传输控制块 TCB
,用于数据传输过程的控制。通常包括:
- 地址信息(对方的 ip、端口号)
- 序列号(需要接收的下一个字节在字节流中的编号。用于跟踪字节流传输。)
- 窗口大小(发送窗口大小、接收窗口大小,用于限制发送速度和接收速度。)
- 超时和重传信息(重传计时器、往返时间。发送方根据这些信息判断数据是否丢失)
- 发送和接收缓冲区(缓冲已发送未确认的信息,用于重传;缓冲已接收未校验未或读取的数据,用于校验和应用读取)
- ...
TCP报文分段
TCP 会主动对数据进行分段,这是为了实现流量控制、拥塞控制和重传。通过控制数据段的长度,可以实现发送速率的动态调控。通过对数据的分段,可以避免发送失败时将全部数据重传,减小重传开销。
最大报文段长度(MSS)
通常受到底层 MTU 的限制,因为需要避免数据段被 IP 层再次分片带来额外开销。
TCP 报文首部
名词解释:
序号
占 4 字节,范围是 [0,2^{32}-1],共 2^{32}(即4294967296)个序号。指示的是数据段在完整数据中的位置。TCP是面向字节流的,因此这里的序号是按照字节编号的。确认号
占 4 字节,是期望收到对方下一个报文段的第一个数据字节的序号。假设已经收到 100 字节,那么回复的确认帧中确认号应为 101。数据偏移
占 4 位,这个字段实际上是指出TCP报文段的首部长度。保留部分
占 6 位,为0。用于标志位将来可能的扩展。标志位
占 6 位,其中- URG 是紧急标志位,用于启用
紧急指针
; - ACK 是确认标志位,用于启用
确认号
; - PSH 是推送标志位,用于通知接收方立即推送缓存给应用;
- RST 是复位标志位,用于通知接收者连接出现不可逆的错误,需要重新建立连接;
- SYN 是同步标志位,在请求建立连接、回应请求建立连接的时候置 1。用于告知对方己方选择的初始
序号
。 - FIN 是结束标志位,在最后一个报文段中置 1。用于请求释放连接。
- URG 是紧急标志位,用于启用
窗口
占 2 字节,是接收方要求的发送方调整的发送窗口大小。用于流量控制 (例如,接收方的缓冲大小不足时,可以通知发送方减小发送窗口,避免数据丢失) 等。校验和
占 2 字节,使用伪首部和数据部生成。伪首部的格式和上文 UDP 伪首部的格式相同,但需要将协议类型值的 0x11(UDP的协议类型号) 改为 0x06(TCP的协议类型号),报文长度改为 TCP 报文段的长度。
拥塞控制
互联网的硬件资源并不是无限的。如果短时间内过多的数据被注入到网络中,超过了路由器等通信设备的缓存极限,不得不丢弃收到的网络包,就会陷入无法发送、也无法接收的拥塞状态(特别是对于 TCP 这类需要来回发送信息才释放资源的协议)。
因此,我们需要一种控制技术,防止一次性有过多的数据进入互联网。
TCP 使用四个算法进行拥塞控制:慢开始、拥塞避免、快重传、快恢复。已有文章将算法讲的很清楚,此处贴上链接:
https://blog.csdn.net/m0_37962600/article/details/79993310
三次握手🤝
TCP 建立连接的时候需要发送三个报文段,因此被称为"三次握手"。
三次握手全过程可以概括如下:(1) 主机 P1 向 P2 发送“请求建立连接”的报文段。(2) P2 收到了请求,于是向 P1 发送“确认你的请求,我也请求建立连接”的报文段。(3) P1 收到了确认和请求二合一的报文段,于是申请维护连接的资源,同时回复 P2 “确认你的请求”。(4) P2 收到确认报文段,于是申请维护连接的资源。
然而,尽管请求能得到确认,但确认本身也有可能丢失而无法确认。这就是著名的蓝白军问题,即不存在一种绝对可靠的方法,能够让通信双方同时确认连接已正确地建立。三次握手思想在于,确保了通信双方各自执行了一次:请求连接、确认请求 的过程,在收到第一次确认后,就已经可以认为连接已建立,可以申请资源。
下面是三次握手中报文段的具体内容:
SYN、ACK 即同步、确认标志位,seq 是 TCP 头部中的 序号,ack 则是 TCP 头部中的确认号。