计算机网络
本篇着重网络层及以上
为什么做此笔记:互联网应用层变幻无穷,但其底层的基石,核心思想和原则不会改变,值得铭记。此外,有些是为了面试,有些是实际开发会遇到的、有些则是为了扩展见识。
电话、无线电技术和互联网的关系?
- 电话(有线):最初依赖铜线实现点对点语音通信,核心是 “专用语音传输网络”(如公共电话网 PSTN)。
- 电话的变革:传统有线电话逐渐被 “IP 电话”(如微信语音、Skype)替代,语音数据通过互联网传输,不再依赖专用电话网;手机通信(蜂窝网络)也与互联网融合,形成 “移动互联网”(4G/5G 既是移动通信网,也是互联网接入网)。电话网变成了互联网的 “语音服务分支”,互联网变成了电话网的 “核心承载平台”,再也分不开。
- 风险⚠️:诈骗手段升级,利用两网互通特性精准诈骗。比如伪基站(模拟运营商信号)结合互联网信息泄露,伪造官方号码发送诈骗短信,诱导点击钓鱼链接。
- 无线电(无线):突破有线限制,通过电磁波传输语音 / 信号,解决了移动、远距离无线通信需求(如广播、早期移动通信)。
- 无线电的拓展:无线电技术成为互联网的 “无线接入手段”(如 Wi-Fi、蓝牙、卫星互联网),负责将终端(手机、电脑)接入互联网;同时,无线电与互联网结合催生了新应用(如物联网设备通过无线电传输数据到互联网平台)。
- 互联网:以 IP 协议为核心,搭建了 “通用数据传输平台”,可承载语音、文字、视频等各类数据,打破了电话、无线电的 “专用网络壁垒”。
Internet(互联网)概述
通信模型的经典举例
互联网最常用的通信模型——可靠的双向字节流,将网络抽象成简单的读写关系
三个例子: World Wide Web(HTTP)、BitTorrent、Skype
万维网(World Wide Web)是客户端-服务端模型
BitTorrent 是对等模型,大量客户端互相打开连接交换数据片段,通过种子传递哪个客户端包含完整的数据片段,形成密集网络
Skype 两者兼备,对于可以直接连接的双方进行对等连接 ,有时客户端无法直接打开连接(客户端在 NAT 后面),通过 Rendezvous (搭桥)服务器或中继服务器连接。
补充 1:
- P2P(Peer-to-Peer,点对点)是一种网络通信架构理念,核心是节点(用户设备)之间直接交互,无需中心服务器中转。
- BitTorrent (简称 BT)是基于 P2P 架构设计的文件分发协议 / 技术,专门用于高效传输大文件,完全遵循 P2P 的通信逻辑。
- 种子(Torrent 文件):并非实际文件,而是一个包含文件元信息(如文件名、大小、块哈希值)和 “Tracker 服务器地址” 的小型配置文件。用户通过加载 Torrent 文件,可连接到 Tracker 服务器获取当前正在传输该文件的用户(“对等节点”)列表。
补充 2:
- WebRTC 核心采用 对等(P2P)模型,同时保留 “中继服务器辅助” 的混合设计,和 Skype 的模型逻辑一致。当客户端在 NAT 或防火墙后无法直接通信时,用 STUN 服务器(地址发现工具)获取客户端的公网地址和端口,帮助双方发现彼此。若 STUN 穿透失败,会通过 TURN 服务器(数据中继兜底)临时中继数据。连接建立的协商过程(如媒体格式、加密密钥),会通过信令服务器(需开发者自行部署或使用第三方)完成,信令服务器不参与实际数据传输。信令服务器对应 Skype 模型的 Rendezvous 服务器。
TCP/IP 四层模型
自上而下:Application、Transport、Network、Link
Link(链路层/网络接口层)
互联网由主机(host)、链路(link)、路由器(router)组成。数据在链路上逐跳传递(hop by hop),数据以数据包的形式传递。数据包包括数据和报头,每次传递一个链路的数据,报头告诉网络数据包要传递到哪里,从哪里来。路由器根据路由转发表的字段判断下一跳将数据包传到哪里。
traceroute 命令可以追踪你链路层传入目标主机每一跳的链路
1 | traceroute bilibili.com |
链路层就是为了传递链路上的数据,Ethernet (以太网)和 WiFi 就是不同链路层的例子
Network(网络层)
网络层就是为了端到端地传递数据包,跨越整个互联网,从源头到目的地。
在网络层数据包叫做数据报(datagrams),网络将数据报交给链路层并告诉他下一链路的位置。

我们向互联网发送数据包时必须使用互联网协议(Internet Protocol)——IP
Transport(传输层)
将数据包按顺序,无损坏且必要时重新传输给应用程序,则需要另一个运行在 IP 之上的协议,这是传输层的工作。最常见的是 TCP,即Transmission Control Protocol(传输控制协议)。不需要可靠的传递,使用更简单的 UDP ,即 Use Datagram Protocol(用户数据报协议)。
Application(应用层)
应用程序之间预期以双向可靠的字节流传输,由应用层的协议定义两个端点数据流的语法和语义。例如 HTTP(Hypertext Transfer Protocol)——超文本传输协议。GET 请求定义了以 ASCII 码发送请求。

网络层
IP 的细节
IP 使用简单的机制捕获并删除卡在循环的数据报(使用TTL,达到 0 去自动丢去该数据报)。(循环可能是由于路由转发表错误或正在更改)
IP 会为数据分片。例如,以太网只能承载 1500bytes 的数据包,别的链路层又可能限制更小的数据报,那么这个链路会接着分。
IP 使用报头校验和减少数据报传递到错误目标的可能性
现在使用的 IP 地址分为 IPv4 (32 bit)和 IPv6(128 bit)
IP 允许在数据报报头中添加新字段

IP 报文(IPv4)的前 8 字节(64 位)包含版本、头部长度、服务类型、总长度、标识、标志、片偏移这几个核心字段。第 9 字节开始,继续包含生存时间、协议、头部校验和、源 IP 地址、目的 IP 地址等核心信息,完整头部(最小 20 字节)
了解:封装是一种将协议层组合成数据包的干净简单的方式,使得每一层使用数据包的方式都与其他层无关。详细可了解虚拟专用网络(VPN)如何使用封装
了解:主机判断是通过路由器发送数据还是直接发送到本地节点是根据目标 IP 地址与子网掩码的按位与运算,再和自身 IP 与子网掩码的运算结果对比。最长前缀匹配(LPM)是 IP 路由器用来决定如何转发数据包的算法。
IP 协议数据的最大大小(MTU)标准值是1500 字节。
地址解析协议(ARP)
地址解析协议(ARP)是网络层发现与其直接连接的网络地址关联的链路地址的机制。
当数据在同一局域网内传输时,数据无需经过路由器跨网络,此时必须通过 MAC 地址定位目标设备 —— 通常只知道目标的 IP。此时电脑会在局域网内广播一条 “ARP 请求”,寻找 IP 地址,局域网内所有设备都会收到这条请求。只有目标 IP 的设备会应答,你的电脑收到回应后,会把 “IP 地址 - MAC 地址” 的对应关系存到本地的 “ARP 缓存表” 里,下次直接从这个缓存传递数据。
运输层
TCP
TCP 用了四个机制确保了数据的可靠按序传输
- 确认(Acknowledgments):用于表明数据已被正确送达。
解释:接收方收到数据后,会给发送方回传 “确认消息”,以此告知对方 “数据我收到了”。 - 校验和(Checksums):用于检测数据是否损坏。
解释:发送前给数据计算一个 “校验值”,接收方重新计算并比对,若不一致则说明数据在传输中被篡改 / 损坏。 - 序列号(Sequence numbers):用于检测数据是否缺失。
解释:给每个数据块按顺序编号(比如 1、2、3),接收方发现编号不连续(比如收到 1、3),就知道 “2 号数据丢了”。 - 流量控制(Flow-control):用于防止接收方被数据 “淹没”。
解释:如果发送方发得太快,接收方处理不过来,会通过流量控制告知发送方 “慢一点”,避免接收方缓冲区溢出。
TCP 三次握手、四次挥手

TCP 建立连接需要进行三次握手。(A 主动向 B 建立连接)
第一次:A 向 B 发送 Syn(Synchronize ,同步)消息,表明 A 的 TCP 层想要与 B 的 TCP 层建立连接。还会发送用于标识字节流中字节的序列号。(下面会详细提到)
第二次:B 回复 ACK+Syn+序列号,ACK 表明 B 正在确认 A 的请求宁同意建立通信,Syn 表示 B 的 TCP 层想要与 A 的 TCP 层建立连接。A发送后进入Established 状态。
第三次:首先会检查 ISNb 和 ISNa 的差值,以确认服务器返回的 Ack请求是否是合法的符合预期的。合法的话,A 回复 ACK,表明接受了 B 的反方向通信的请求,服务器端收到就进入 Established 状态。非法就回 RST 报文,服务器收到就释放此链接。
详细看后面 TCP 状态机。

TCP 关闭连接需要进行四次挥手。(A 主动向 B 关闭连接)
- 第一次:A 的 TCP 层发送 FIN 消息表示关闭连接
- 第二次:B 发送ACK确认 A 没有任何数据要发送,关闭了来自 A 的数据流。此时也携带着 B 到 A 的仍有可能没发完的新数据。
- 第三次:当 B 发送完数据后,发送 FIN 告诉 A 可以关闭连接
- 第四次:A 发送 ACK 回复,确认连接现在要关闭
RST 报文与正常关闭(FIN)的核心区别
| 维度 | RST 报文(强制复位) | FIN 报文(正常关闭) |
|---|---|---|
| 作用 | 强制终止异常 / 无效连接,无需协商 | 正常关闭连接,需双方 “四次挥手” 确认 |
| 资源释放 | 立即释放连接相关资源 | 逐步释放,需等待对方确认 |
| 触发场景 | 端口未开放、连接失效、程序崩溃等 | 应用主动发起关闭(如关闭浏览器) |
TCP 报文段格式
TCP 连接通过 TCP 和 IP 首部的五部分信息进行唯一标识

TCP 连接的发起者选择唯一的源端口号时,使用简单的方法降低选择重复连接的相同源端口号的可能,即新连接递增端口号。端口号是 16bit,因此超过 64k 个新连接会导致端口号重复。
同时创建大量新连接(例如 TCP 段在网络停留很长时间,卡在路由器缓存区中)也可能导致创建两个具有相同的标识(五部分信息相同),此时字节流会发生混淆。为了减少这种混淆,TCP 使用随机的初始序列号(Sequence)来表示字节流中的字节。

- 源端口(Source port)
- 占 16 位(2 字节),表示发送方应用程序的端口号,用于标识数据是哪个应用发出来的(比如浏览器用 80/443 端口)。
- 目的端口(Destination port)
- 占 16 位(2 字节),表示接收方应用程序的端口号,用于标识数据要发给对方的哪个应用(比如服务器的 80 端口对应 HTTP 服务)。
- 序列号(Sequence # (of first byte))
- 占 32 位(4 字节),表示当前 TCP 段中第一个字节的序号。
- 作用:让接收方按序号重组数据,检测丢失 / 重复的段。
- 确认序列号(Acknowledgment Sequence #)
- 占 32 位(4 字节),表示期望接收的下一个字节的序号(即已成功收到的最后一个字节的序号 + 1)。
- 作用:告诉发送方 “我已经收到了到 XX 序号的数据,你可以发下一个了”。
- 头部长度(HLEN)
- 占 4 位,单位是 “4 字节”,表示TCP 头部的总长度(因为 TCP 头部可能有选项,所以长度不固定)。
- 比如 HLEN=5 → 头部长度 = 5×4=20 字节(TCP 头部最小长度)。
- 保留位(RSVD)
- 占 6 位,预留未使用(通常设为 0)。
- 标志位(Flags,共 6 个,每个占 1 位)
- ACK:确认位。为 1 时,“确认序列号” 字段有效(表示这是一个确认段)。
- URG:紧急位。为 1 时,“紧急指针” 字段有效(表示段中有紧急数据)。
- PSH:推送位。为 1 时,接收方应立即把数据交给应用(不缓存)。
- RST:复位位。为 1 时,强制关闭连接(用于处理错误 / 异常)。
- SYN:同步位。为 1 时,用于建立连接(发起方发 SYN 请求,对方回 SYN+ACK)。
- FIN:终止位。为 1 时,用于关闭连接(表示 “我没有数据要发了”)。
- 窗口大小(Window Size)
- 占 16 位,表示接收方当前能接收的最大字节数(流量控制的核心字段)。
- 作用:告诉发送方 “我现在最多还能收这么多数据,别发太多了”。
- 校验和(Checksum)
- 占 16 位,用于检测 TCP 段(头部 + 数据)是否损坏(发送方计算,接收方验证)。
- 紧急指针(Urgent Pointer)
- 占 16 位,只有 URG=1 时有效。表示紧急数据在当前段中的结束位置(指向紧急数据的最后一个字节)。
- TCP 数据(TCP Data)
- 可选字段,是实际要传输的应用层数据(比如 HTTP 请求、文件内容等)。
UDP
UDP 被用于不需要 TCP 保证交付服务的应用使用,或者应用自己重传。
UDP 只做:接受应用数据,创建 UDP 数据报,交给网络层
UDP 报文段格式

- 源端口(Source port)
- 占 16 位(2 字节),表示发送方应用程序的端口号。
- 作用:接收方需要回复时,能通过这个端口找到对应的发送应用;若不需要回复,也可以设为 0。
- 目的端口(Destination port)
- 占 16 位(2 字节),表示接收方应用程序的端口号。
- 作用:标识数据要发给对方的哪个应用(比如 DNS 服务用 53 端口)。
- 长度(Length)
- 占 16 位,单位是 “字节”,表示整个 UDP 数据报的总长度(包含 UDP 头部 + UDP 数据)。
- 范围:最小值是 8 字节(仅头部,无数据),最大值是 65535 字节(受 IP 数据报长度限制)。
- 校验和(Checksum)
- 占 16 位,用于检测 UDP 数据报(头部 + 数据)是否损坏。
- 注意:UDP 的校验和是可选的(但实际应用中通常会启用),而 TCP 的校验和是强制的。
- UDP 数据(UDP Data)
- 可选字段,是实际要传输的应用层数据(比如 DNS 查询、视频流数据等)。
UDP 的头部只有 8 字节(是 TCP 头部最小长度的 1/2.5),所以它的开销小、传输效率高,但没有 TCP 的可靠 / 按序 / 流量控制等功能。
了解:DNS 、DHCP(动态主机配置协议)、NTP (网络时间协议)使用 UDP 协议。向 DNS 服务器发送包含主机名的 DNS 请求,DNS 服务器会响应 IP 地址,不需要建立连接。请求不成功会简单地超时并重试
ICMP——互联网控制报文协议(Internet Control Message Protocol)
ICMP是网络层的 “辅助协议”:不传输用户数据,而是传递网络状态(比如 “目标不可达”“超时”),典型应用是ping(检测主机连通性)和traceroute(追踪路径跳数)。
这三种机制使互联网中的网络层正常工作
- 互联网协议(IP)
- 负责创建 IP 数据报。
- 实现端到端的逐跳交付。
- 路由表
- 通过算法来填充路由器的转发表。
- 互联网控制消息协议(ICMP)
- 在终端主机和路由器之间传递网络层信息。
- 报告错误情况。
- 帮助诊断网络问题。
ICMP 的服务模型很简单:发送错误报告、作为简单不可靠的协议
一些 ICMP错误类型

tarceroute 原理是是源主机发送 TTL=要测量的下一跳的路由器的长度的UDP 协议,数据包丢失后返回 ICMP 消息,可以得到路由到的主机名,计算时间 UDP 发送与 ICMP 接受的时间差得到用时,然后 TTL++,继续下去。直到目标主机,此时 UDP 会携带错误的端口号触发 ICMP 错误(type=3)并返回。这样就得到了完整的路由链。
三种检错机制
1. CRC 校验(循环冗余校验)
- 核心定位:纯粹的检错机制,不涉及身份验证。
- 执行位置:主要在数据链路层(如以太网 MAC 帧的 FCS 字段),部分硬件传输场景(如 DDR 内存总线)也会应用。
- 核心作用:检测数据传输中的随机错误(如比特翻转、信号干扰导致的损坏),无法防范人为篡改。
- 关键特点:计算效率高,适合硬件快速实现,检错能力强。
2. 校验和(Checksum)
- 核心定位:跨分层的检错机制,同样不涉及身份验证。
- 执行位置:覆盖运输层(TCP/UDP)、网络层(IP)、应用层(如 HTTP ETag),均在端系统或路由器的对应分层执行。
- 核心作用:检测数据 / 协议头部的传输错误,TCP/UDP 校验和覆盖数据 + 头部,IP 校验和仅覆盖头部。
- 关键特点:计算简单(多为求和取反),检错能力弱于 CRC,适合对效率要求高于检错精度的场景。
3. MAC(消息认证码)Message Authentication Code
- 核心定位:密码学安全机制,兼具完整性验证和身份认证。
- 执行位置:仅在端系统的应用层执行。
- 核心作用:既验证数据未被篡改(完整性),又确认发送方持有合法密钥(防伪造、防抵赖),能防范人为恶意篡改。
- 关键特点:需依赖共享密钥和特定算法(如 HMAC-SHA256),计算开销高于 CRC 和校验和,安全性更强
- JWT 签名机制(HS256/HS512 等)、使用传输层安全协议(TLS)的 HTTP 请求(HTTPS)属于 MAC 的应用场景
端到端原则
确保文件传输正确的唯一方法是进行端到端检查,而不是在链路层检查(链路错误检测是只为了检测传输过程的错误,而不是存储过程的错误)。
端到端原则的核心是:网络核心(如路由器、交换机)应保持简单,只提供基础的数据包转发,复杂的通信功能(如可靠传输、加密、纠错)应放在网络边缘的端系统(如主机、服务器)中实现。
Finite State Machines (有限状态机)
有限状态机(Finite State Machine) 是一种数学模型,核心是 “状态 + 触发条件 + 状态转移”—— 包含有限个固定状态,通过特定事件(触发条件)从一个状态切换到另一个,且同一状态下相同事件的转移结果固定,像 “按规则切换模式的机器”。
生活类比:电梯(状态:静止、上行、下行;触发条件:按楼层按钮、到达目标层;转移逻辑:静止时按上行键→上行状态)。
经典的 FSM 例子:TCP 连接

1. 连接建立阶段(三次握手)
TCP 通过 “三次握手” 建立可靠连接:
- 阶段 1:客户端(处于
CLOSED)发SYN请求,进入SYN SENT状态; - 阶段 2:服务端(处于
LISTEN监听状态)收到SYN,回复SYN+ACK,进入SYN RECEIVED状态; - 阶段 3:客户端收到
SYN+ACK,回复ACK,双方进入ESTABLISHED(已建立连接)状态,此时可开始数据传输。
2. 数据传输阶段
双方处于ESTABLISHED状态时,可互相发送 / 接收数据(图中 “Data exchange occurs”)。
3. 连接关闭阶段(四次挥手)
TCP 通过 “四次挥手” 关闭连接,分为主动关闭和被动关闭两种角色:
- 主动关闭方(比如客户端):
- 发
FIN请求关闭,进入FIN WAIT 1; - 收到对方的
ACK,进入FIN WAIT 2; - 收到对方的
FIN,回复ACK,进入TIME WAIT(等待超时,确保对方收到ACK); - 超时后回到
CLOSED。
- 发
- 被动关闭方(比如服务端):
- 收到
FIN,回复ACK,进入CLOSE WAIT; - 发自己的
FIN,进入LAST ACK; - 收到对方的
ACK,回到CLOSED。
- 收到
图中不同颜色的箭头区分了 “客户端→服务端”(红色)和 “服务端→客户端”(蓝色)的通信路径,虚线则表示异常事件触发的状态跳转
Flow Control(流量控制)
核心逻辑
- 不要发送超出接收方处理能力的数据包
- 接收方向发送方提供反馈
- 两种基本方法
▶ 停等协议(Stop-and-Wait Protocol)
▶ 滑动窗口法
停等协议
原则:
- 任何时刻最多只有一个数据包在传输中
- 发送方发送一个数据包
- 接收方收到数据后,发送确认数据包
- 发送方收到确认后,再发送新的数据
- 若超时,发送方重发当前数据
停等协议的有限状态机

停等协议的有限状态机(FSM),分为接收方(Receiver FSM)和发送方(Sender FSM)两部分,对应之前说的 “发 - 等 - 确认” 逻辑:
1. 接收方状态机(Receiver FSM)
只有 1 个状态:Wait for Packets(等待数据包)
- 行为:收到数据后,做两件事 ——
- 给发送方发确认包(send ack);
- 把数据交给上层应用(deliver data);
- 之后回到 “等待数据包” 状态,循环处理下一个包。
2. 发送方状态机(Sender FSM)
有 2 个状态,流程是 “等待数据 → 等待确认 → 循环”:
状态 1:Wait for Data(等待上层数据)
行为:当上层软件调用 “发送”(software calls send),就发送数据包,然后进入下一个状态。
状态 2:Wait for ACK(等待确认)
行为:
- 收到确认包(receive ack packet)→ 回到 “等待上层数据” 状态,准备发下一个包;
- 超时(timeout)→ 重发当前数据包(resend),继续停在 “等待确认” 状态。
整个状态机直观体现了停等协议 “一发一收一确认” 的核心逻辑,是可靠传输的基础模型之一。
执行案列

- No Loss(无丢包)
- 流程:发送方发
data→接收方收到后发ACK→发送方收到ACK,准备发下一个包。 - 说明:理想的正常传输场景,“一发一收一确认” 顺利完成。
- Data Loss(数据丢包)
- 流程:发送方发
data→数据包丢失→发送方超时→重发data→接收方收到重发的data,发ACK→发送方收到ACK。 - 说明:通过 “超时重传” 解决数据丢包问题。
- ACK Loss(确认包丢包)
- 流程:发送方发
data→接收方收到并发ACK→ACK丢失→发送方超时→重发data→接收方收到重复data,再次发ACK→发送方收到ACK。 - 说明:通过 “超时重传” 解决确认包丢包问题(接收方需能识别重复数据)。
- ACK Delay(确认包延迟)
- 流程:发送方发
data→发送方在ACK因网络延迟还没到达,误以为data丢失而重发data→ACK到达发送方→发送方发送新的data→发送方收到ACK,但不清楚这个是重复数据的ACK还是新数据的ACK
- 流程:发送方发
- 说明:抛出来新问题,如何知道新数据是重传数据还是数据包的副本还是新数据
对发送和确认使用比特计数器/1 位计数器

1. 核心机制:1 位计数器(0/1 标识)
- 在数据包(data)和确认包(ACK)中加入 1 位序号(只有 0 和 1 两种值):
- 发送方发
data 0,接收方回ACK 0; - 下一个包发
data 1,接收方回ACK 1; - 再下一个包又回到
data 0,循环交替。
- 发送方发
- 作用:接收方通过序号判断数据是 “新包” 还是 “重复包”(比如收到
data 0时,若上一个处理的是data 0,则判定为重复)。
2. 简化假设(协议的前提条件)
为了让 1 位计数器逻辑成立,做了 3 个简化:
- 网络不会主动复制数据包(即不会出现额外的重复包);
- 数据包不会延迟超过 “多个超时时间”(避免旧包延迟过久导致序号混淆)。
滑动窗口
停等协议很简单,但一次只能传输一个数据包,收到确认后再发下一个,效率极低
滑动窗口协议一次可以发送多个数据包
滑动窗口发送方
每个分段都有一个序号(SeqNo)
维护 3 个变量
▶ 发送窗口大小(SWS)
▶ 最后收到的确认(LAR)
▶ 最后发送的分段(LSS)
保持不变式:(LSS - LAR) ≤ SWS
收到新确认时更新 LAR
缓存最多 SWS 个分段
滑动窗口接收方
维护 3 个变量
▶ 接收窗口大小(RWS)
▶ 最后可接受的分段(LAS)
▶ 最后收到的分段(LSR)
保持不变式:(LAS - LSR) ≤ RWS
若收到的数据包序号 < LAS,则发送确认
▶ 发送累积确认:例如收到 1、2、3、5,确认 3
▶ 注意:TCP 的确认是 “下一个期望接收的数据”(比如上述例子中会确认 4)
RWS、SWS 与序号空间
RWS ≥ 1,SWS ≥ 1,且 RWS ≤ SWS
若 RWS = 1,对应 “回退 N 步(Go-Back-N)” 协议,需要 SWS+1 个序号
若 RWS = SWS,需要 2×SWS 个序号
通常需要 RWS+SWS 个序号
▶ RWS 个数据包处于 “未知状态”(确认可能丢失 / 未丢失)
▶ 传输中的 SWS 个数据包不能超出序号空间的范围
核心逻辑总结
允许一个 “窗口” 的未确认数据包处于传输中
当确认包到达时,窗口向前滑动
所需的序号空间大小取决于窗口大小
应用层
网络要做的事情就是寻找最佳路径来传输数据包,而所有的处理都应该在边缘的应用层进行。
想构建一个互联网程序,就必须得了解 NAT是怎么样工作的,这是一个复杂的因素。
NAT(网络地址转换)
如今的绝大部分家用无线路由器都是 NAT,ISP(Internet Service Provider)互联网服务提供商会给你的路由器分配 公网IP,不过大部分家用路由器没有自己的公网IP,通过上级的共用路由器的WAN 口 IP 进行路由。
NAT 可以给它后面的内部设备分配不同的私有 IP 地址,并将他们转化为唯一的公网地址,内部设备通过 NAT 访问外部时,NAT 将其私有 IP 地址和端口转换为自己的 IP 地址和端口,通过这个 NAT 的IP 地址与外部通信,接收到消息再转发回原本内部设备的 IP 地址和端口。因此这样可以保证安全性,你的连接不会轻易被外部打开。工作流程就是简单的映射,将地址至内部接口翻译到外部接口。
Full Cone NAT (全锥 NAT)
NAT 的映射表只绑定内部设备 IP+端口和 NAT 的 IP 的端口。只要映射关系存在,任何外部设备都能通过访问 “公网 IP + 公网端口”直接连接到内部设备映射的端口。
Restricted Cone NAT (受限锥 NAT)
此时,NAT 的映射表还会绑定远程主机的 IP,只要映射关系存在,无论该远程主机用哪个端口,都能通过已建立的NAT端口与内网设备通信。但是其他没有绑定远程主机 IP ,通常不会翻译该数据包或者发送 ICMP 错误。
Port Restricted NAT(端口受限 NAT)
此时,NAT 的映射表会绑定远程主机的 IP 和端口号。只有映射表存在的对应远程主机的 IP 和端口号才能与内部设备进行连接。
Symmetric NAT(对称 NAT)
这时候的映射表为每一个 “内网 IP + 内网端口 + 目标公网 IP + 目标公网端口” 的组合,分配一个唯一的公网端口。这样会导致无固定 “内网端口→公网端口” 对应关系,同一内网设备访问不同目标,公网端口动态变化。也就是说即使内部设备的出端口相同,但是换了远程服务器,连接会终止。
Incoming Connection 传入连接
主机在NAT 后,传入连接一般是不能的。
方法一:一方在 NAT 后,一方不在:
引入 rendezvous service (交汇服务),实现连接反转。由 B 到 A 反转为A 到 B。R 在这里是交汇服务

方法二:双方都在 NAT 下,引入中继服务器(Relay),转发双方互相发送的流量
方法三:采取更激进的操作,来直接打开连接,其中一种方法是 NAT 穿透
全锥 NAT 下,让内部设备 A连接外部服务器后,其 IP 和端口被映射进 NAT,服务器可以把这个暴露在公网的 IP 和端口告诉另一端 B,另一端 B就可以通过 NAT 连接到 A。如果是受限锥 NAT 或端口受限 NAT,从服务器知道对方 IP 和端口后则会强制建立映射。
该方法不适用于对称 NAT,因为只要访问的 “目标公网 IP / 端口” 变化,之前的公网端口就会失效,需重新分配 NAT 的新端口

为了让应用程序在互联网上正常工作,必须使用 TCP、UDP、ICMP 的其中一个传输协议,因为NAT 需要识别传输协议的头。
NAT对于 TCP、UDP 的最佳实践:RTC5382、RTC4787
ICE 服务器(Interactive Connectivity Establishment Server,即交互式连接建立服务器)允许查询自己处于哪种 NAT 后面,以及判断与他们本地 IP 地址和端口相关联的外部 IP 地址和端口,通过 rendezvous 服务交换这些信息。在 WebRTC 中,Rendezvous 服务常搭建于信令服务器中,其核心职责 —— 转发双方的 ICE 候选地址(设备通过 ICE 服务器获取候选地址后,会把地址发给信令服务器,再由信令服务器转发给对方)。
NAT 类型检测工具:NAT类型检测工具 - 在线检测NAT类型和网络连接性 - 17NAS
HTTP(HyperText Transfer Protocol)——超文本传输协议
HyperText 只是一种文档,浏览器根据这些特殊的格式化命令和标签来显示它。使用超文本,你可以将文档和文件嵌入其中。
HTTP 请求体格式
HTTP 响应体格式

1 | # 使用telnet 打开 TCP 连接 |
BitTorrent
1. Torrent 文件的核心作用
.torrent文件是 BT 下载的 “索引文件”,用来描述要下载的文件信息,包含以下关键内容:
- 指明Tracker 服务器:这个服务器负责记录哪些用户(Peer)正在参与该文件的下载 / 上传(即 “种子” 和 “ peers”)。
- 记录文件的元数据:包括文件总大小、文件被分割成的 “分片(piece)” 大小,以及每个分片的 SHA1 哈希值(用于验证分片的完整性,防止下载到损坏 / 篡改的内容)。
- 附加元数据:比如创建这个 torrent 文件的作者、创建时间等信息。
2. BT 下载的流程(基于 Torrent 文件)
当你用 BT 客户端打开.torrent文件后:
- 客户端先连接到 Torrent 文件里指定的Tracker 服务器;
- 从 Tracker 获取当前参与下载的其他 Peer 列表;
- 开始和这些 Peer 通信,互相下载 / 上传文件分片。
3. “无 Tracker” 的 Torrent(Trackerless)
有些 Torrent 不依赖 Tracker 服务器,而是用DHT(分布式哈希表):
- swarm(下载群体)的信息(Peer 列表)会分散存储在多个节点上;
- 通过分布式协调机制,客户端可以直接从其他节点获取 Peer 信息,不需要中心化的 Tracker。
文件分片交换策略
Peer 间交换分片元数据
Peer 会互相告知 “自己拥有哪些文件分片”,这样每个节点都知道从谁那里能下载到缺失的分片。
优先下载最稀有的分片(Rarest First 策略)
优先获取当前 swarm 中拥有者最少的分片,避免某个分片因持有者过少而 “失传”,保证整个下载群体能更快集齐所有分片。
最后几个分片的多节点请求
当只剩少量分片未下载时,会同时向多个 Peer 请求这些分片,加快收尾速度(避免因单个 Peer 离线导致最后几片下不动)。
BitTyrant(一种 BT 客户端 / 策略),核心是 “利用 BT 的‘Tit-for-Tat(以牙还牙)’机制来提升下载速度”:
1. 核心问题:能否 “钻 BT‘以牙还牙’机制的空子”?
BT 的 “以牙还牙” 规则是:Peer 会优先给 “上传给自己数据多的节点” 解除限速(unchoke)。而 BitTyrant 的思路是通过策略优化,用最少的上传代价获得最多的下载权限。
2. BitTyrant 的策略
- 只给对方上传 “刚好能让它解除对自己限速” 的少量数据;
- 尽可能让更多的 Peer 对自己解除限速;
- 把上传带宽分散给更多 Peer(而不是集中给少数 Peer)。
3. 效果
这种策略能让下载性能中位数提升 70%—— 因为用更少的上传资源,换来了更多 Peer 的下载权限。
简单说:BitTyrant 是一种 **“优化” BT 上传策略的工具 **,通过 “最小化上传、最大化下载权限” 来提高下载速度,属于对 BT 机制的 “利用性优化”。
总结
1. 基础文件:Torrent 文件(.torrent)
它是 BT 下载的 “索引”,描述要下载的文件信息(比如文件结构、分片哈希等)。
2. 文件分片与验证
要下载的文件会被拆分成多个 “分片(piece)”,每个分片都有对应的 SHA1 哈希值 —— 用来验证下载的分片是否完整 / 未被篡改。
3. 找到其他下载节点(Peer)
客户端通过两种方式获取 Peer 列表:
- Tracker 服务器:中心化的节点列表服务器;
- DHT(分布式哈希表):去中心化的方式,从其他节点获取 Peer 信息。
4. 连接与通信
客户端之间通过TCP/IP 协议建立连接,进行数据传输。
5. 分片信息交换
客户端会互相告知 “自己拥有哪些分片”,这样每个节点都知道从谁那里能下载缺失的分片。
6. 分片下载策略:优先下最稀有分片
客户端会优先下载当前下载群体中 “拥有者最少的分片”(rarest-piece-first),避免某个分片因持有者太少而 “失传”。
7. 上传限速规则:以牙还牙(Tit-for-Tat)
客户端会对大部分 Peer“限速(choke)”,只给 “上传给自己数据最多的 P 个 Peer” 解除限速 —— 你给我传得多,我就优先给你传。
DNS(Domain Name System)——域名系统
URL(Uniform Resource Locator)统一资源定位符的组成:协议头、主机的域名或 IP、文件。
早期互联网中,所有主机的 “域名 - IP 对应关系” 都记录在一个叫 HOSTS.TXT 的文件里,由网络信息中心(Network Information Center)维护。这个文件的存储地址是 SRI-NIC.ARPA(对应 IP:26.0.0.73),相关规范在 RFC952 中定义。
各个主机需要定期通过文件传输协议下载最新版本的 HOSTS.TXT,以此更新自己的域名 - IP 映射表。这种方案的网络开销是 n² 量级(n 是主机数量)—— 随着主机增多,下载和同步 HOSTS.TXT 的成本会急剧上升,完全无法支撑互联网的扩张。
因此,DNS 应运而生。
DNS 的设计逻辑
1.让 DNS 设计可行的两个核心属性
DNS 能替代 HOSTS.TXT,靠的是这两个特点:
- 只读 / 读多写少的数据库:主机查询域名的频率,远高于更新域名 - IP 映射的频率(比如你每天查很多域名,但很少去修改某个域名对应的 IP)。
- 弱一致性:域名信息的变更可以 “延迟扩散”—— 不需要立刻同步到所有节点,短时间的不一致是可接受的(比如域名解析结果更新后,部分缓存节点晚一点同步也不影响核心功能)。
2. 支持大规模缓存的两个属性
这两个特点让 DNS 可以广泛使用缓存(减少重复查询,提升效率):
- 查询一个域名后,结果可以长时间保留(缓存)—— 因为域名 - IP 映射不会频繁变化,缓存有效期内重复查询直接用缓存结果即可。
ps:鲁棒性是Robustness的中文译法,核心是系统或算法在异常、干扰或不确定环境下,仍能保持正常功能的能力。
DNS 分布式架构的关键
1. 层级化的 “区域(Zones)”
DNS 服务器按层级划分区域,比如从顶层的 “根区域(root zone)”,到一级域名(如 edu)、二级域名(如 stanford)、子域名(如 scs),形成树状结构。
2. 区域的独立管理
每个区域可以单独管理—— 比如 “edu” 区域由教育机构管理,“stanford” 由斯坦福大学管理,各自负责自己区域内的域名解析。
3. 区域的多服务器副本
每个区域会部署多个副本服务器,避免单点故障,提升可靠性。
4. 根区域的细节
- 根区域最初有13 台服务器(标识为 a 到 m),实际通过 “任播(anycast)” 技术进行大量复制(让不同位置的用户访问最近的根服务器)。
- 根服务器的 IP 地址会预先存储在 DNS 服务器的文件中(作为 “启动引导”,让 DNS 系统能先找到根服务器)。
简单说:这是 DNS 的分布式层级架构设计—— 通过区域拆分、独立管理、多副本服务器,实现了全球域名解析的高效与可靠。

DNS 查询的完整流程(以 “客户端查www.example.com” 为例):
客户端→本地解析器(递归查询)
客户端(如浏览器)向本地 DNS 解析器(通常是路由器或运营商 DNS)发起递归查询:“请帮我查到www.example.com的 IP”。
解析器→根域名服务器(迭代查询)
解析器先查自己的缓存,若没有则向根域名服务器发起非递归查询:“请问www.example.com的 IP 是什么?”
根服务器回复:“我不知道它的 IP,但.com 域名的权威服务器在这几个地址,你去问它们”。
解析器→顶级域名(TLD)服务器(迭代查询)
解析器向.com 的 TLD 服务器发起非递归查询:“请问www.example.com的 IP 是什么?”
TLD 服务器回复:“我不知道它的 IP,但example.com的权威服务器在这几个地址,你去问它们”。
解析器→权威域名服务器(迭代查询)
解析器向example.com的权威服务器发起非递归查询:“请问www.example.com的 IP 是什么?”
权威服务器回复:“www.example.com对应的 IP 是 192.0.2.1”。
解析器→客户端(返回结果)
解析器将 IP 结果返回给客户端,并把结果缓存起来(后续同域名查询可直接用缓存)。
关键概念:
- 递归查询:客户端→解析器的请求是 “你必须给我结果”,解析器负责全程处理。
- 迭代查询:解析器→根 / TLD / 权威服务器的请求是 “你不知道的话,告诉我下一步该问谁”,解析器自己一步步向下查。
RR
每个 DNS 消息都以资源记录(Recourse Records)的事物表示,格式为:
1 | name [TTL] [class] type rdata |
每个字段的含义:
- name:对应的域名(比如
www.stanford.edu)。 - TTL:生存时间(单位:秒)—— 决定该记录在 DNS 缓存中的保存时长,超时后会重新查询。
- class:用于扩展(比如支持不同网络),实际中几乎只用
IN(代表 Internet,值为 1)。 - type:记录的类型(决定
rdata的内容)。 - rdata:资源数据 —— 内容由
type决定,是记录的核心信息。
两个核心的 RR 类型:
- A 记录:对应 IPv4 地址
type=A时,rdata是域名对应的 IPv4 地址(比如www.example.com的 A 记录,rdata 是192.0.2.1)。
- NS 记录:对应域名服务器
type=NS时,rdata是负责该域名解析的权威服务器域名(比如example.com的 NS 记录,rdata 是ns1.example.com)。
DNS 消息的结构
DNS 消息的结构(遵循 RFC1035 标准),是 DNS 查询 / 响应的数据包格式,核心分为 5 个部分:
- Header(头部):固定长度的元数据区域,包含消息类型(查询 / 响应)、返回码(是否成功)、各部分的资源记录数量等控制信息。
- Question(问题):仅在查询请求中存在,包含要查询的域名、记录类型(如 A 记录)等查询参数。
- Answer(答案):仅在响应消息中存在,包含查询域名对应的资源记录(比如 A 记录的 IP 地址)。
- Authority(权威):仅在响应消息中存在,包含负责该域名解析的权威服务器信息(NS 记录)。
- Additional(附加):仅在响应消息中存在,包含辅助信息(比如权威服务器对应的 IP 地址),避免额外的查询请求。
dig是一个常用的 DNS 查询工具,可以直接获取域名对应的各类资源记录(比如用dig www.stanford.edu A就能查到它的 A 记录)。
Exp:
1 | (base) xixiu@xixiudeMacBook-Air ~ % dig bilibili.com |
手动使用非递归查询指定域名
1 | dig +norec www.scs.stanford.edu @arg[xxx] |
+norec:表示禁用递归查询(让 DNS 服务器只返回自己知道的结果,不帮我们向下查询);www.scs.stanford.edu:要查询的目标域名(斯坦福大学计算机科学系的子域名);@arg[xxx]:@后面是指定的 DNS 服务器地址(图中显示不完整,比如@8.8.8.8就是指定用谷歌 DNS 查询)。
作用:问xxx我下一步应该找谁去查询www.scs.stanford.edu对应的IP呢
exp:
1 | (base) xixiu@xixiudeMacBook-Air ~ % dig +norec www.bilibili.com @a.root-servers.net |
根服务器不存储具体域名的 A 记录,所以返回:
ANSWER:0(没有直接答案);AUTHORITY:13(返回.com顶级域名的权威服务器列表,比如a.gtld-servers.net);ADDITIONAL:27(返回这些.com权威服务器的 IP 地址);- 意思是 “我(根服务器)不知道
www.bilibili.com的 IP,你去问.com的权威服务器”。
CNAME 记录
CNAME 全称 “Canonical name record(规范名称记录)”,作用是将一个域名标记为另一个域名的 “别名”。
格式为:
1 | name [TTL] [class] CNAME canonical-name |
name:别名域名canonical-name:目标(规范)域名别名关联:规范域名的所有记录(如 A 记录),都会同时关联到别名域名。
排他性:设置了 CNAME 的别名域名,不能再配置其他 DNS 记录(如 A、MX 等)。
规范域名可多记录:规范域名本身可以同时配置其他 DNS 记录。
MX 记录
MX 全称 “Mail eXchange record(邮件交换记录)”,作用是指定某个域名对应的邮件服务器(即该域名的邮件要发送到哪个服务器)。
格式为:
1 | name [TTL] [class] MX preference mail-server-name |
name:域名(比如scs.stanford.edu)preference:优先级(数字越小,优先级越高)mail-server-name:对应的邮件服务器域名域名的 “邮件专属” 属性:比如
scs.stanford.edu可能无法被 ping 通(没有 A 记录对应 IP),但可以正常接收邮件(因为有 MX 记录指定了邮件服务器)。依赖 A 记录MX 记录里的
mail-server-name必须对应 A 记录(否则邮件无法投递)。例:用
dig mx scs.stanford.edu可以查询该域名的 MX 记录;若mail-server-name没有 A 记录,用dig mx bad-mx.scs.stanford.edu会显示异常。
其他记录
1. SOA(Start of Authority)
是域名区域的 “权威起始记录”,包含域名的核心管理信息(比如主 DNS 服务器、管理员邮箱、数据更新周期等),每个域名区域必须有且只有一条 SOA 记录。
2. TXT
是任意文本记录,用于存储自定义文本信息,常用于扩展功能(比如验证域名所有权、配置 SPF 邮件防伪造、DKIM 邮件签名等)。
3. PTR
是反向解析记录,作用是把 IP 地址映射为域名(和 A 记录 “域名→IP” 的正向解析相反),常用于邮件服务器身份验证等场景。
4. AAAA
是IPv6 地址记录,作用是将域名映射到 IPv6 格式的 IP 地址(类似 A 记录对应 IPv4 地址)。
DHCP(Dynamic Host Configuration Protocol)——动态主机配置协议
根据前文,我们已经知道了:
要实现 IP 通信,设备至少需要 3 个关键参数:
- IP 地址:设备在网络中的唯一标识(类似 “门牌号”)。
- 子网掩码:用来区分 IP 地址中的 “网络段” 和 “主机段”,确定设备所属的子网。
- 网关路由器:当设备要和其他子网的设备通信时,数据会先发送到网关,由网关转发(类似 “小区大门”)。
实用但非必需的配置(1 项)
- DNS 服务器 IP 地址:用于将域名解析为 IP 地址(方便访问网站),但它不是 IP 通信的必要条件(没有 DNS 也能通过 IP 直接通信)。
这些配置参数是如何获取的?
早期的网络配置方式
过去是由系统管理员提供 IP、子网掩码等参数,用户手动输入到网络控制面板里。
1995 年在布朗大学时还需要这么做,毕业时这种方式就被淘汰了。
手动配置的弊端
这种方式存在很多问题:
- 设备移动后失效:设备换了网络环境(比如换个办公室),之前的配置就用不了了。
- 有效期不明确:不知道配置的参数能使用多久。
- IP 地址管理混乱:没用的 IP 地址难以回收(类似 “垃圾回收” 问题)。
1. DHCP 的基本定义
DHCP(RFC 2131 标准)是一种让设备自动从 DHCP 服务器请求网络配置的协议,替代了手动输入参数的方式。
2. DHCP 解决的痛点
针对之前手动配置的问题,DHCP 的优化:
- 设备移动适配:设备换网络后,重新向 DHCP 服务器请求配置即可。
- 配置有效期:参数有 “租期(lease)”,到期前可以续租。
- IP 地址回收:租期到期后,未续租的 IP 会被自动回收(解决 “垃圾回收” 问题)。
3. DHCP 的核心流程
通信过程分为 5 个步骤(图中标记了客户端 / 服务器的交互):
- Discover(发现):客户端广播请求 DHCP 服务器。
- Offer(提供):服务器响应,提供可用的 IP 等配置。
- Request(请求):客户端选择其中一个配置并请求确认。
- Ack(确认):服务器确认配置,客户端开始使用。
- Release(释放):客户端主动释放配置(比如关机时)。
DHCP 在 “无 IPv4 配置时” 的通信方式(对应 DHCP 初始阶段,设备还没获取到 IP 的场景)
1. 传输层与端口
DHCP 使用UDP 协议通信,固定端口分配:
- 服务器端用端口 67
- 客户端用端口 68
2. 网络层的广播方式
因为客户端此时还没有 IP 地址,所以会通过广播 IP 地址 255.255.255.255发送请求(让同一子网内的 DHCP 服务器都能收到)。
3. 跨子网的中继方案
如果 DHCP 服务器不在当前子网,需要通过 DHCP 中继(Relay) 来转发请求,实现跨链路的配置分配。
简单说,DHCP 在设备 “还没 IP” 的阶段,靠 UDP + 固定端口 + 广播(或中继)来完成初始通信,从而获取 IP 等配置。