从可靠字节流到 P2P 通信
共同的基础:双向可靠字节流
网络应用虽然用途不同,但都可以建立在同一种抽象上:两台机器上的程序之间有一条双向、可靠的字节流。一端按顺序写入字节,另一端按顺序读出字节;应用只需要规定这些字节代表什么。
HTTP:客户端向固定服务器要文档
Web 的常见模式是客户端—服务器:浏览器向一个公开可访问的服务器发请求,例如 GET /index.html;服务器返回内容和状态码,例如 200、404 或 502。
HTTP 请求和响应示例是人能直接读懂的文本,图片、视频等响应体可以是二进制数据,现代 HTTP/2、HTTP/3 的底层帧也不是纯文本。
BitTorrent:许多客户端共同分发一个文件
BitTorrent 中没有唯一的数据服务器。拥有同一文件的客户端下载、上传,构成一个 swarm(集群)。文件被分成许多 pieces(片段),所以一个客户端可以同时向多个 peer 请求不同片段,下载完后也把已有片段分享给别人。
下载前,客户端会从 .torrent 文件获得文件的描述和 tracker 信息。tracker 的主要工作是发现:告诉客户端“有哪些 peer 可能拥有这个文件”;数据本身通常仍在 peer 之间传输。
A 向 tracker 查询文件 X ↓tracker 返回一批候选 peer ↓A 尝试连接其中可达的 peer,并交换 pieces所以 BitTorrent 也需要某种“找人”的机制(tracker、DHT 等),并不是天然不受 NAT 影响。只是它通常不执着于连接某一个特定用户:某个 peer 连不上时,可以换另一个有相同片段的 peer。
NAT:为什么个人设备不容易被主动连接
家庭路由器或移动网络常使用 NAT(网络地址转换)。家里的多台设备可以共享同一个公网 IP;路由器用端口和一张临时映射表区分不同设备。
电脑 A1: 192.168.1.10:50000 ──> 公网 203.0.113.7:40001电脑 A2: 192.168.1.11:50000 ──> 公网 203.0.113.7:40002当 A1 主动访问外部服务器时,NAT 建立映射。服务器随后发回 203.0.113.7:40001 的数据,NAT 就能交给 A1。
问题在于外部机器若想新建一条到 A1 的连接,NAT 往往没有对应的映射,不知道该把数据交给哪台内网设备,于是通常丢弃。简化地说:NAT 后的设备容易主动出站,外部却不容易主动入站。
Skype:需要找到并通知“特定的 B”
课程中的 Skype 例子是历史教学模型。A 想呼叫的是指定用户 B;若 B 在 NAT 后,A 直接连 B 可能失败。此时需要公网的 rendezvous(会合)服务器 R。
关键点是:B 登录时先主动连到 R,并保持一条控制连接。A 发起呼叫后,R 不会从外部新开一条连接闯进 B;它只是沿 B 已经建立的连接,把“有人呼叫你”的消息写回给 B。
B ──先主动连接──> RA ──“我要呼叫 B”──> RR ──沿 B 的既有连接通知──> B这条连接能穿过 NAT,是因为 B 出站时已建立映射;R 发回的是这条既有连接的返回流量。实际系统会保持连接或定期发送 keepalive,避免映射因空闲过期。
收到通知后:
- 若 A 可被访问,B 可以主动连接 A。这叫反向连接:呼叫意图来自 A,但建连动作由 B 发起;连上后数据仍可双向传输。
- 若 A、B 都在 NAT 后且无法打洞或端口映射,则双方分别主动连接公网 relay(中继)服务器,由中继转发语音、视频或聊天数据。
A ──> relay ──> BB ──> relay ──> A会合服务器主要传递“谁在找谁、是否接听”等控制消息,开销较小;relay 位于实际数据路径上,需要转发媒体流量,因此是直连失败时的保底方案。
三者的区别
| 应用 | 主要问题 | 辅助角色 | 数据通常怎么走 |
|---|---|---|---|
| HTTP | 向固定服务器请求资源 | 服务器 | 客户端 ↔ 服务器 |
| BitTorrent | 找到任意拥有片段的 peer | tracker / DHT | peer ↔ peer |
| Skype | 通知并连接指定的用户 | rendezvous;失败时 relay | 优先直连,失败时经 relay |
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时






