跳转至

传输层 — 进程到进程的可靠传输

这一章讲全书前半段的落点:TCP。 IP 把分组送到机器门口就走了(尽力而为、不保证顺序、不保证到达); 传输层接过包裹,做到两件事:递对门(同一台机器上几十个程序,哪个才是收件人?)和 管到底(丢了补、乱了排、多了扔、快了刹——全是 IP 不管的)。 UDP 只解决第一件事,TCP 两件事全包。读懂这一章,你就读懂了为什么「IP 不可靠 而互联网可靠」不是一个悖论,而是一份分工合同。

1. 传输层站在哪:主机到进程的最后一公里

网络层的通信主体是主机——分组从一个网络层出发,经路由器转发,到达另一个网络层1。 但两个主机通信,实际是主机上应用进程之间的通信。传输层给上层提供的 正是「端到端的逻辑通信」:应用进程看不见底下什么介质、什么拓扑, 只看见一条通向对端进程的通道——走 TCP 是可靠的信道,走 UDP 是不可靠的信道2。

传输层还有一层结构意义:OSI 里它是低三层(通信网)与高三层(面向应用)的中介, 「为面向应用的高三层屏蔽与网络有关的低三层的详细操作」3——第 01 章那句 「端到端可靠性」的架构裁决,在这里变成具体机制。

2. 顶层全景:一个网页请求的传输层剖面

主线例子(贯穿本章): 浏览器(你的电脑,客户端)向 Web 服务器请求一个网页。 传输层视角下发生的事:

  3.2 端口:服务器在 80 端口等,浏览器用一个随机端口(如 49152)发起 —— 「哪扇门」
  3.5 三次握手:SYN → SYN+ACK → ACK,双方确认对方在、商定起始序号 —— 「连线」
  3.6 数据传输:请求与响应按字节编号、累计确认;接收方用窗口通告还能吃多少 —— 「对话」
  3.6 拥塞控制:拥塞窗口从 1 个报文段指数爬升,撞墙(超时/3 个重复 ACK)再退 —— 「礼让」
  3.5 四次挥手:FIN → ACK → FIN → ACK,半个方向先关、另一个还能继续 —— 「挂线」
  3.8 socket:你的浏览器和服务器程序,都是经由 socket 这套 API 使用上面这一切

3. 核心原理

3.1 端口:进程的地址

一台主机只有一个 IP 地址,却跑着几十个网络程序——网络层送到主机之后, 靠端口号区分交给哪个程序。端口是传输层与应用层接口处的编号, TCP 和 UDP 的报文头里都各有源端口和目的端口4。

复用与分用(第 01 章留过的问题)由此闭环:发送方,各应用的报文都经各自的端口 交下来,套上 TCP/UDP 头(含端口号)后统一交给 IP——复用; 接收方,IP 交上来的报文按端口号分发给对应的应用——分用5。 同一台 Web 服务器上 80 端口归 HTTP、25 端口归邮件,互不串台。

端口的分配(16 位,0~65535)分两档:

范围 名称 谁来分
0~1023 熟知端口 IANA 全局分配,绑定特定服务:80=HTTP,25=SMTP,21=FTP,53=DNS
1024~49151 注册端口 松散绑定各种服务
49152~65535 动态/私有端口 操作系统本地随机分配,客户端临时用

「小于 256 的作为保留端口」是老规矩,今天按 0~1023 记6。书里同时交代了 全局分配与本地分配两种机制:知名服务的端口全球统一(任何机器上 80 都是 HTTP), 客户端的临时端口由本机操作系统发7。

3.2 UDP:极简的另一半

UDP 在 IP 之上只加了两样东西:端口(复用/分用)和校验和(差错检测)8。 没有连接、没有确认、没有重传、没有拥塞控制、没有状态——发出去就忘。

为什么这样的协议还有大用处,四条理由9:

  1. 不用建连——省掉握手往返,首包即达(DNS 查询就是因为它才快);
  2. 无连接状态——服务器不用为每个客户端维护状态表,同样的内存能服务上万人;
  3. 头开销小——UDP 头 8B,TCP 头至少 20B;
  4. 应用层完全掌控发送时机——没有拥塞控制替你降速,实时语音宁可丢包也不要延迟抖动。

UDP 报文头只有四个字段(各 2B):源端口、目的端口、长度(头+数据)、校验和。 校验和的计算有个细节:要在 UDP 报文前面临时加一个 12B 的伪首部(含源 IP、目的 IP、 协议号等)——它不属于 UDP 头,只为让校验和顺带校验「这对 IP 地址」, 防止 IP 层误投的报文蒙混过关10。

哪些应用在 UDP 上跑:DNS、DHCP、SNMP、RIP(v1/v2)、IP 电话、流式多媒体、IGMP…… 书里的表 7-1/8-1 值得对一眼:每个应用的选择都有理由——交互少、要求快、自己能忍丢包、 或协议本身就是「一问一答」的,选 UDP;要可靠字节流的,选 TCP11。 代价书里也写明:用了 UDP,超时重传、编号防重这些都得应用自己实现12。

3.3 TCP 提供的服务:可靠的、全双工的字节流

TCP 的五大承诺13:

  1. 面向连接:通信前先建连,数据沿连接传,完事释放;
  2. 可靠性:每个字节都编号;收方对最后一个按序收到的字节回确认(累计确认); 发方超时没等到确认就重传;
  3. 字节流:应用把数据交给 TCP 就好,TCP 自行决定切成多大的段—— 应用看到的是连续的字节流,不是一个个包;
  4. 流量控制:接收方用窗口字段通告自己的缓冲余量,发方不得超过;
  5. 全双工:双方沿同一条连接同时双向收发。

TCP 报文段格式(头至少 20B)14:

  源端口(16) | 目的端口(16)
  序号(32)      —— 本段数据第一个字节的编号
  确认号(32)    —— 我期望收到的下一个字节号(之前的全收到了)
  数据偏移(4) | 保留(6) | URG ACK PSH RST SYN FIN | 窗口(16)
  校验和(16) | 紧急指针(16)
  选项(≤40B,常用:MSS)

序号与确认号是理解 TCP 的钥匙,主线例子立刻用: 客户端发了一个序号 301、 长 100B 的段,服务器收妥后回的确认号就是 401—— 「401 以前的全到了,下一个我要 401」15。六个标志位各管一件事: SYN(建连)、FIN(收工)、ACK(确认号有效)、RST(复位,出错了重来)、 PSH(催接收方快点上交)、URG(有紧急数据,配合紧急指针用)。

窗口字段(16 位)是流量控制的阀门:填的是「从确认号起,我还能收多少字节」。 MSS(最大报文段长度)选项在握手时互通:「我的缓存最多能吃这么长的段」, 于是 TCP 切段不超过路径 MTU——这就是现代 TCP 尽量不触发 IP 分片的机制(第 06 章的伏笔收线)。

3.4 三次握手:为什么必须三次

连接建立要解决两个问题:双方都在线吗?各自的初始序号是多少(防止旧连接的报文 溜进新连接)?过程(书里的图 7-9)16:

  客户端                          服务器
    │── SYN=1, SEQ=x ───────────▶│  「我想连你,我的序号从 x 起」(LISTEN)
    │◀────── SYN=1, ACK=1, ──────│  「同意,我的序号从 y 起,已收到 x」(SYN-RCVD)
    │        SEQ=y, ACKSEQ=x+1   │
    │── ACK=1, SEQ=x+1, ────────▶│  「收到你的同意」(ESTABLISHED)
    │        ACKSEQ=y+1          │      (双方都 ESTABLISHED)

两条细则: SYN 段不携带数据,但要消耗一个序号;纯 ACK 段不携带数据就不消耗序号17。 为什么是三次而不是两次? 两次握手的漏洞:客户端的一个迟到 SYN 姗姗来迟, 服务器收到就单方面建连、分配资源、等待数据——客户端早已不认这笔账, 服务器的资源被白白占着(这正是 SYN 洪泛攻击的原理,第 11 章会再见)。 第三次 ACK 让服务器确认「客户端真的在等这次连接」——同步必须是相互的。

3.5 连接释放:四次挥手与 2MSL

TCP 是全双工,两个方向的连接要分别关闭——所以是四次18:

  A(先说完)                    B
    │── FIN=1, SEQ=u ──────────▶│  A→B 方向:我没话了(FIN-WAIT)
    │◀──── ACK=1, SEQ=v, ───────│  B 答:知道了(CLOSE-WAIT)
    │        ACKSEQ=u+1         │      (B 还可以继续往 A 发!)
    │   ...(B 把剩余数据发完)...  │
    │◀──── FIN=1, ACK=1, ───────│  B→A 方向:我也没话了(LAST-ACK)
    │        SEQ=w, ACKSEQ=u+1  │
    │── ACK=1, SEQ=u+1, ───────▶│  A 答:知道了 → TIME-WAIT
    │        ACKSEQ=w+1         │

中间那个「半关闭」状态是全章最妙的细节:A 说完了、B 确认了, 但 B 还有话没说完,连接在这个方向上继续传——「我没有数据要发送了, 但如果你还发送数据,我仍接收」19。TCP 把一条全双工连接当两条单工连接分别管理。

TIME-WAIT 与 2MSL:发出最后 ACK 的 A 不立即消失,而是等待 2 倍报文最大生存时间。 为什么?若最后的 ACK 丢了,B 会重传 FIN,等着再答一次;更根本的是, 让本次连接的迟到报文在 2MSL 内全部死绝,不与下一条使用相同四元组 (源IP,源端口,目的IP,目的端口)的新连接混淆20。「服务器重启后一时连不上」, 八成就是 TIME-WAIT 堆着。

3.6 流量控制:窗口是接收方手里的刹车

TCP 用可变滑动窗口做流量控制:接收方根据自己的缓冲余量动态改窗口值, 发方把「未确认的字节数」压在窗口以内21。

主线例子(书里的图 7-12 简化): 初始窗口 4096B,序号从 0 开始——

  ① 客户端发 2KB(SEQ=0),服务器缓冲占 2KB,回 ACK=2048, WIN=2048
  ② 客户端再发 2KB(SEQ=2048),服务器应用一直没来取数,缓冲占满!
     回 ACK=4096, WIN=0  ←—— 「别再发了」
  ③ 客户端收到 WIN=0,停发;直到服务器应用取走 2KB,
     回 WIN=2048,客户端续发(SEQ=4096)

窗口 0 之后还有个经典难题:服务器后来发的「WIN=2048」若丢失,双方互相等死。 解法(补充,不在书中详述):窗口探测报文——发方周期性发 1 字节探针,收方必须回应。 (顺带一提:这和第 03 章停等协议「等 ACK」是同构的,窗口只是把批量放大了。)

发送窗口的双重约束:发送窗口 = min(接收窗口, 拥塞窗口)22。 接收窗口 Rwnd 是「别撑死对方」,拥塞窗口 Cwnd 是「别撑死网络」—— 流量控制保护接收方,拥塞控制保护网络,下一节就是它。

3.7 拥塞控制:给看不见的网络把脉

拥塞:对某资源的需求超过了它的可用部分,网络性能就要变坏23。 症状:路由器队列越来越长、时延越来越大、最终丢包——而丢包又触发更多重传, 恶性循环。TCP 的处境很被动:IP 层不告诉它哪里拥塞,一切只能靠猜—— 用丢包(超时或重复 ACK)当作网络的呻吟。

慢启动:指数爬升。 新连接开始,不知道网络容量,就先轻踩: 拥塞窗口 Cwnd 从 1 个 MSS 起,每收到一个确认就加 1 个 MSS—— 1、2、4、8……指数翻倍,几轮 RTT 就探到带宽上限24。

拥塞避免:线性前进。 指数增长太凶,得有个门槛——慢启动阈值 ssthresh: Cwnd < ssthresh 走慢启动(指数);Cwnd > ssthresh 走拥塞避免—— 每过一个 RTT 加 1 个 MSS(不管这一 RTT 收到几个 ACK),线性爬25。

遇到丢包,两种病两种药26:

信号 判断 动作
超时(重传计时器到期) 网络很严重 ssthresh = Cwnd/2;Cwnd 直接打回 1,重新慢启动
3 个重复 ACK(快重传) 网络还通,只丢了一个 ssthresh = Cwnd/2;Cwnd = ssthresh(不必回到 1),进入快恢复

主线例子把全过程画一遍(书里的图 7-13 同款:ssthresh 初值 8MSS):

  Cwnd(MSS)
   12 ┤            ×超时!ssthresh=12/2=6,Cwnd=1
   10 ┤          × ╱╲      重新慢启动到 6,
    8 ┤        ×   ╱  ×    再线性爬到 8 又超时…
    6 ┤      ×     ╱    ×
    4 ┤    ×   线性段(每 RTT +1)
    2 ┤  ×
    1 ┤×
      └───┴───┴───┴───┴──→ RTT 轮次
      指数段(每 ACK +1)

这套「加性增、乘性减」(AIMD)被写进 RFC 2581,与快重传、快恢复并称四算法27: 快重传——不等超时,连收 3 个重复 ACK 立即重传丢失的段; 快恢复——重传后 Cwnd 设为 ssthresh+3×MSS(那 3 个重复 ACK 说明 3 个包还在管线上), 继续拥塞避免而不是回慢启动28。

3.8 重传计时器:RTT 怎么测,怎么信

可靠传输的最后一环:超时时间设多久?太短,白重传、添乱;太长,真丢了又干等。 难点在传输层的 RTT 方差极大——链路层 RTT 分布集中,传输层穿的是整个 Internet, 时延忽大忽小(书里的图 7-14)29。

TCP 的答案是加权平均 + 自适应:

  平均 RTT = α × 旧平均 + (1−α) × 新测量      (α 典型 7/8——旧值权重大,平滑)
  重传时间 = β × 平均 RTT                      (β 原标准推荐 2)

Karn 算法处理一个测量悖论:重传之后收到了 ACK——这个 ACK 是对原段的还是对重传的? 分不清,测出来的 RTT 就是假的。对策:凡重传过的段,它的 RTT 样本一律不采30。 副作用:网络真的变慢时 RTT 永远测不到新值。补丁:每重传一次,重传时间 ×2(γ=2)—— 超时翻倍退避,直到不再重传才恢复按 RTT 计算31。

3.9 套接字:应用层摸得到的把手

socket 是对「不同主机上应用进程双向通信端点」的抽象——应用进程上连 socket、 下连协议栈,是应用层与 TCP/IP 之间的接口,也是操作系统提供的网络 API(API 就是程序调用操作系统功能的固定入口清单)32。

「IP 地址 + 端口号」唯一标识网络中的一个进程,这就是一个 socket; 两端 socket 组成 socket 对(socket pair),唯一标识一条连接33。 三类:流式(SOCK_STREAM,走 TCP,可靠有序)、数据报(SOCK_DGRAM,走 UDP)、 原始(SOCK_RAW,直接摸 IP/ICMP)。

基于 TCP 的通信流程(书里的图 7-15)——这几乎是所有网络服务的通用骨架:

  服务器:socket() → bind(绑定端口) → listen(开始监听) → accept(阻塞等客)
  客户端:socket() → connect(指向服务器的 IP:端口)      → 建立连接
  双方:  write()/read() 反复通信 → close()
  服务器 accept 返回后,通常另起线程/进程继续服务,自己回去 accept 下一个

主线例子的代码视角: 浏览器与 Web 服务器就是这条流水线的两端——服务器 80 端口 listen,浏览器 connect 发起三次握手(对程序而言是 connect 一次调用), 握手细节全藏在协议栈里。UDP 版本更简单:没有 listen/accept/connect 的次序, 双方各 bind 一个端口,sendto/recvfrom 即发即走34。

3.10 传输层的报文级细节补遗

UDP 校验和怎么算(书里的图 7-7 展示了完整的计算例)38:发送方把伪首部、UDP 头、 数据按 16 位分段求和(反码加法),结果取反填入校验和字段;接收方把同样的全套 (含填好的校验和)再算一遍,结果应为全 1(即反码的 0),不是则说明传输中出了错。 UDP 的校验和有个和 TCP 不同的细节:它是可选的——数据不含校验和字段置 0 表示 「不校验」(在可信的本地网络可以省掉这点开销);TCP 的校验和则是强制的。

TCP 头部的六个标志位一句话各表39:URG(紧急指针有效)、ACK(确认号有效)、 PSH(别攒着,立即上交应用)、RST(连接出错了,强制复位)、SYN(建连同步序号)、 FIN(本方数据发完了)。排障时的口头禅「RST 刷屏」——就是对方或中间设备在强制 拆你的连接(端口没监听、防火墙拦截、超时……)。

连接建立的状态机视角(书里的图 7-9 标注了每个阶段双方的状态名)40:

  客户端:CLOSED ──发SYN──▶ SYN-SENT ──收SYN+ACK──▶ ESTABLISHED
  服务器:CLOSED ──监听──▶ LISTEN ──收SYN──▶ SYN-RCVD ──收ACK──▶ ESTABLISHED

netstat/ss 命令里看到的连接状态名全部出自这张表。半连接队列(SYN 队列)与 全连接队列(accept 队列)的长度——服务器扛不扛得住突发连接洪峰,就看这两处, 这是书里 SYN-SENT/SYN-RCVD 状态在工程上的回声。

慢启动的精确节奏(把 3.7 的图再对一遍书里的图 7-13)41: ssthresh 初始 8MSS。第 1 轮发 1 个段,Cwnd→2;第 2 轮发 2 个,Cwnd→4; 第 3 轮发 4 个,Cwnd→8——第 4 轮触线(ssthresh=8),转入拥塞避免: 此后每轮成功 Cwnd 只 +1(8→9→10…),直到第 8 轮 Cwnd=12 时超时。 处置:ssthresh 砍半到 6,Cwnd 重置 1,重新慢启动;第 2 次爬到 6 转线性, 到 9 又超时,ssthresh=4……锯齿形曲线就是这样一圈圈锯出来的。 这条锯齿的数学性质(每轮翻倍、撞墙砍半)决定了 TCP 在丢包网络下的吞吐上限。

socket 的类型与选型(3.9 流程图之外的三个细节)42:SOCK_STREAM 的「流」意味着 没有消息边界——应用层要自己解决「一条消息从哪到哪」(协议里加长度字段或分隔符); SOCK_DGRAM 保留边界但不保证到达、不保证顺序;SOCK_RAW 直接摸 IP/ICMP, 给 ping、traceroute、抓包工具这类「自己动手丰衣足食」的程序用(通常要管理员权限)。 服务器端 accept 返回的是新的 socket(专门服务这个客户端), 原来的那个继续 listen——「一个门面接客,后厨一对一服务」。

4. 作者的判断与证据

  • 「端到端才有可靠」的兑现:TCP 章不引入任何网络内部机制——拥塞控制靠端系统 猜丢包,流量控制靠端系统互告窗口,与第 01 章的架构裁决严格自洽35;
  • 「慢启动不慢」:书明说初始速率很慢、但指数增长极快,名字里的「慢」指的是起点 而不是趋势36;
  • 四次算法的成文依据(RFC 2581)与线路误码率极小的前提(「分组丢失的概率很小」) 并列给出37——拥塞控制的全部大厦,建立在「丢包≈拥塞」这个统计假设上。

5. 边界与局限

  • 拥塞控制一章是 RFC 2581 的经典算法族;近年的改进(BBR 用带宽与 RTT 建模、 QUIC 在用户空间重做拥塞控制)不在本书范围,但 AIMD 的丢包哲学仍是理解它们的起点。
  • 定时器细节按原版 TCP 讲:今天的实现普遍用 Jacobson/Karels 偏差算法(RTT 方差 参与计时),书里只有加权平均 + Kam 补丁的雏形。
  • socket 一节只给流程不给代码;错误处理、并发模型( select/epoll、IO 多路复用) 一概未提——这是「网络原理」与「网络编程」的分工边界。
  • TCP 头选项(窗口扩大、时间戳、SACK)未展开,只提了 MSS——而 SACK 对现代 高速网络的重传效率至关重要。

判断(我们的,不是书里的): 这一章是全书对你写代码回报最直接的一章: 「为什么 connect 会卡」「为什么下载到 99% 不动了」「为什么内网飞快外网慢」, 答案全在这章的机制里。特别值得带走的是 AIMD 的思维方式:对一个看不见、 问不动的系统(网络、数据库、线程池),用「试探—惩罚—回退—再试探」的节奏逼近 容量上限,是通用的工程智慧——限流器、连接池、批量处理,处处是它的影子。 如果错,会错在: 「丢包=拥塞」的前提正在被动摇——无线误码与缓存膨胀 (bufferbloat)会让丢包信号撒谎,BBR 等新算法改看带宽与延迟; AIMD 的教学地位短期内不会变,但它作为「最优实践」的时代正在过去。

6. 可带走的

  1. 传输层补两件事:递对程序(端口)、管到送达(可靠性);UDP 只干第一件,TCP 全包;
  2. 端口:0~1023 熟知(DNS 53、HTTP 80、SMTP 25、FTP 21),高端口操作系统发;
  3. UDP = IP + 端口 + 校验和;快、省、无状态,适合一问一答与实时流;
  4. TCP 序号 = 本段首字节号;确认号 = 期望的下一字节号(累计确认);
  5. 三次握手防「迟到的旧 SYN」;SYN 耗序号,纯 ACK 不耗;
  6. 四次挥手因为全双工;半关闭让一方说完另一方还能说;TIME-WAIT = 2MSL 防混淆;
  7. 发送窗口 = min(接收窗口, 拥塞窗口)——别撑死对方 × 别撑死网络;
  8. 拥塞控制:慢启动指数爬、过 ssthresh 线性增、超时打回 1、3 重复 ACK 减半(AIMD);
  9. RTT 用加权平均测,重传样本不采(Karn),超时翻倍退避;
  10. socket:IP+端口标识进程;服务器 socket→bind→listen→accept,客户端 socket→connect。

7. 原文地图

主题 原书章 原文位置
传输层定位与端到端 第7章传输层 text/17-ch07.txt:7(搜「中介」) · text/17-ch07.txt:14(搜「应用进程之间的逻辑通信」)
TCP/UDP 总览与信道 第7章传输层 text/17-ch07.txt:43(搜「UDP 是一种不可靠」) · text/17-ch07.txt:57(搜「全双工的可靠信道」)
端口与复用分用、三类端口 第7章传输层 text/17-ch07.txt:76(搜「协议端口」) · text/17-ch07.txt:115(搜「熟知端口」)
UDP 优点四条与报文格式 第7章传输层 text/17-ch07.txt:130(搜「无须建立连接」) · text/17-ch07.txt:137(搜「8B」)
UDP 伪首部 第7章传输层 text/17-ch07.txt:197(搜「伪首部」)
TCP 五大服务 第7章传输层 text/17-ch07.txt:214(搜「TCP 提供的服务」)
TCP 报文段格式与序号确认号 第7章传输层 text/17-ch07.txt:239(搜「格式」) · text/17-ch07.txt:265(搜「301」)
三次握手与序号消耗规则 第7章传输层 text/17-ch07.txt:306(搜「连接建立」) · text/17-ch07.txt:325(搜「消耗掉一个序号」)
四次挥手、半关闭、2MSL 第7章传输层 text/17-ch07.txt:376(搜「连接释放」) · text/17-ch07.txt:425(搜「半关闭」) · text/17-ch07.txt:411(搜「2MSL」)
可变窗口流量控制例 第7章传输层 text/17-ch07.txt:435(搜「流量控制」) · text/17-ch07.txt:453(搜「4096B」)
发送窗口 = min(两窗口) 第7章传输层 text/17-ch07.txt:497(搜「MIN」)
拥塞定义与四算法 第7章传输层 text/17-ch07.txt:503(搜「拥塞」) · text/17-ch07.txt:519(搜「RFC 2581」)
慢启动与拥塞避免、ssthresh 第7章传输层 text/17-ch07.txt:526(搜「慢启动」) · text/17-ch07.txt:541(搜「拥塞避免」) · text/17-ch07.txt:546(搜「ssthresh」)
AIMD 与丢包两药方 第7章传输层 text/17-ch07.txt:563(搜「加性增」) · text/17-ch07.txt:565(搜「拥塞控制算法如下」)
快重传快恢复 第7章传输层 text/17-ch07.txt:570(搜「3 个重复」) · text/17-ch07.txt:584(搜「快速恢复」)
RTT 方差与加权平均、Karn 第7章传输层 text/17-ch07.txt:594(搜「重传机制」) · text/17-ch07.txt:617(搜「α」) · text/17-ch07.txt:630(搜「Kam 算法」)
socket 概念与三类 第7章传输层 text/17-ch07.txt:642(搜「套接字概念」) · text/17-ch07.txt:657(搜「SOCK_STREAM」)
TCP/UDP socket 流程 第7章传输层 text/17-ch07.txt:672(搜「bind」) · text/17-ch07.txt:711(搜「UDP 传输数据」)

  1. 出处:「传输层概述」第 10–14 段(text/17-ch07.txt:11,搜「从一个主机的网络层发出」)。 ↩

  2. 出处:「TCP/IP 模型中的传输层」第 54–58 段(text/17-ch07.txt:57,搜「全双工的可靠信道」;text/17-ch07.txt:58,搜「不可靠的信道」)。 ↩

  3. 出处:「传输层概述」第 7–9 段(text/17-ch07.txt:8,搜「屏蔽了下层的通信细节」)。 ↩

  4. 出处:「传输层端口」第 71–82 段(text/17-ch07.txt:76,搜「协议端口」;text/17-ch07.txt:80,搜「TPDU」)。 ↩

  5. 出处:「传输层端口」第 89–97 段(text/17-ch07.txt:89,搜「复用」)。 ↩

  6. 出处:「传输层端口」第 113–122 段(text/17-ch07.txt:115,搜「0~1023」)。 ↩

  7. 出处:「传输层端口」第 104–112 段(text/17-ch07.txt:105,搜「全局分配」;text/17-ch07.txt:111,搜「熟知」)。 ↩

  8. 出处:「用户数据报协议」第 125–129 段(text/17-ch07.txt:127,搜「端口功能」)。 ↩

  9. 出处:「用户数据报协议」第 130–143 段(text/17-ch07.txt:130,搜「无须建立连接」)。 ↩

  10. 出处:「UDP 报文的格式」第 195–199 段(text/17-ch07.txt:197,搜「伪首部」)。 ↩

  11. 出处:「用户数据报协议」表 7-1(text/17-ch07.txt:145,搜「表 7-1」)。 ↩

  12. 出处:「用户数据报协议」第 174–176 段(text/17-ch07.txt:176,搜「并对数据包进行编号」)。 ↩

  13. 出处:「TCP 提供的服务」第 214–237 段(text/17-ch07.txt:218,搜「面向连接」)。 ↩

  14. 出处:「TCP 报文段的格式」第 239–262 段(text/17-ch07.txt:241,搜「头部的前 20B」)。 ↩

  15. 出处:「TCP 报文段的格式」第 263–270 段(text/17-ch07.txt:265,搜「301」)。 ↩

  16. 出处:「TCP 连接管理」第 303–351 段(text/17-ch07.txt:312,搜「SYN」;text/17-ch07.txt:320,搜「三次握手」)。 ↩

  17. 出处:「TCP 连接管理」第 325–326 段(text/17-ch07.txt:325,搜「消耗掉一个序号」)。 ↩

  18. 出处:「连接释放」第 376–386 段(text/17-ch07.txt:383,搜「FIN」)。 ↩

  19. 出处:「连接释放」第 420–426 段(text/17-ch07.txt:425,搜「半关闭」)。 ↩

  20. 出处:「连接释放」第 411 段(text/17-ch07.txt:411,搜「2MSL」)。 ↩

  21. 出处:「TCP 的流量控制」第 435–455 段(text/17-ch07.txt:444,搜「大小可变的滑动窗口」;text/17-ch07.txt:453,搜「4096B」)。 ↩

  22. 出处:「TCP 的流量控制」第 496–501 段(text/17-ch07.txt:497,搜「MIN」)。 ↩

  23. 出处:「TCP 的拥塞控制」第 503–506 段(text/17-ch07.txt:500,搜「拥塞」)。 ↩

  24. 出处:「慢启动」第 526–540 段(text/17-ch07.txt:532,搜「Cwnd=1」;text/17-ch07.txt:540,搜「指数的速度」)。 ↩

  25. 出处:「拥塞避免」第 541–562 段(text/17-ch07.txt:546,搜「慢启动阈值」;text/17-ch07.txt:551,搜「线性增加」)。 ↩

  26. 出处:「拥塞避免」末段(text/17-ch07.txt:565,搜「拥塞控制算法如下」)。 ↩

  27. 出处:「TCP 的拥塞控制」第 519–523 段(text/17-ch07.txt:520,搜「4 种算法」);「拥塞避免」第 563 段(text/17-ch07.txt:563,搜「加性增」)。 ↩

  28. 出处:「快速重传和快速恢复」第 575–590 段(text/17-ch07.txt:580,搜「3 个重复的确认帧」;text/17-ch07.txt:586,搜「ssthresh+3×MSS」)。 ↩

  29. 出处:「重传机制」第 597–601 段(text/17-ch07.txt:597,搜「方差也很大」)。 ↩

  30. 出处:「重传机制」第 627–631 段(text/17-ch07.txt:630,搜「Kam 算法」)。 ↩

  31. 出处:「重传机制」第 632–638 段(text/17-ch07.txt:636,搜「γ」)。 ↩

  32. 出处:「套接字概念」第 640–651 段(text/17-ch07.txt:644,搜「所谓套接字」)。 ↩

  33. 出处:「套接字概念」第 652–656 段(text/17-ch07.txt:261,搜「唯一地标识了网络中的一个主机」)。 ↩

  34. 出处:「套接字连接的实现方式」第 664–719 段(text/17-ch07.txt:672,搜「listen」;text/17-ch07.txt:711,搜「UDP 传输数据」)。 ↩

  35. 出处:「TCP 的拥塞控制」第 508–514 段(text/17-ch07.txt:508,搜「端到端拥塞控制」)。 ↩

  36. 出处:「慢启动」第 538–540 段(text/17-ch07.txt:539,搜「很慢的速率」;text/17-ch07.txt:540,搜「指数的速度」)。 ↩

  37. 出处:「TCP 的拥塞控制」第 521–523 段(text/17-ch07.txt:521,搜「误码」)。 ↩

  38. 出处:「UDP 报文的格式」第 195–206 段(text/17-ch07.txt:197,搜「伪首部」;text/17-ch07.txt:200,搜「这与 TCP 是不同的」)。 ↩

  39. 出处:「TCP 报文段的格式」第 276–286 段(text/17-ch07.txt:278,搜「URG」)。 ↩

  40. 出处:「TCP 连接管理」第 327–351 段(text/17-ch07.txt:330,搜「CLOSED」;text/17-ch07.txt:334,搜「LISTEN」)。 ↩

  41. 出处:「拥塞避免」第 554–562 段(text/17-ch07.txt:555,搜「8MSS」;text/17-ch07.txt:557,搜「Cwnd×0.5」)。 ↩

  42. 出处:「套接字概念」第 657–662 段(text/17-ch07.txt:657,搜「SOCK_STREAM」;text/17-ch07.txt:661,搜「原始 Socket」)。 ↩