P2P 是什么

前阵子我在用一个局域网传输工具,界面上跳出一行小字:"已启用 P2P 加速"。我问家里人 P2P 是什么,得到的回答是"就是下载快一点"。这个答案不算错,但实在太亏了——因为 P2P 背后那套设计,是我今年见过的最漂亮的想法之一。花了两天把资料看完,我决定把它整理成一篇人话版。

一句话:把"所有人都来我这拿",改成"互相拿"

传统做法叫 C/S(客户端 / 服务器):文件放在一台服务器上,一万个人下载,就是这台服务器把同一份数据发一万遍。人越多,服务器越慢,带宽费越贵,而且它一挂,全体下线。

P2P(Peer-to-Peer,点对点)把这件事反过来:每个下载者同时也是上传者。你在下载的时候,已经拿到的部分可以立刻传给下一个人。于是人越多,总带宽越大,速度反而可能更快——这是它最反直觉、也最迷人的地方。

维度C/S 模式P2P 模式
数据来源一台(或一组)服务器所有参与者
用户变多服务器压力变大总上传带宽变大
单点故障有,服务器挂了就全挂没有,谁走了都有人替补
成本带宽费随人数线性上涨分摊到参与者自己的宽带上
管理难度低(都在自己手里)高(无法统一控制)

它要解决三个问题,每一个都不简单

问题一:怎么知道谁手里有文件?

最早的 Napster(1999 年)用的办法很直白:中心索引 + 去中心传输。文件还是从别人的电脑上下,但"谁有这首歌"记在 Napster 自己的服务器上。所以它一被法院要求关掉索引服务器,整个网络就瘫了。

后来的 Gnutella 尝试把索引也分散出去,但简单广播会产生巨量垃圾流量。真正解决问题的是 DHT(分布式哈希表),BitTorrent 用的是其中的 Kademlia:

  • 文件被算出一个哈希值(infohash),这个值本身就决定了"该由哪些节点负责记录"。
  • 每个节点只维护一小部分"邻居",查询时每一步都离目标更近,平均只要 O(log n) 步就能找到。
  • 于是没有一个节点掌握全局,也就没有可以被一锅端的中心。

顺带说一句,磁力链接(magnet)之所以能用,就是因为它只带一个 infohash,剩下的"去哪找"全靠 DHT 现场解决——链接本身就是一条线索,而不是一个地址。

问题二:两个人都躲在路由器后面,怎么连上?

这是最容易被忽略、也最考验工程水平的一环。现在绝大多数设备都在 NAT(网络地址转换)后面,没有公网 IP,外面的人根本"看不见"你。P2P 的解法是打洞(hole punching):

  1. 双方各自向外部的信令服务器打个招呼,服务器于是知道"谁的哪条线路可以通到谁"。
  2. 服务器把这层信息交换给双方,两边同时朝对方的公网出口发包。
  3. 路由器看到自己内网有机器主动发出过这个连接,就允许对方的回包进来——一条通道就这么"打"出来了。

打不通的时候(比如双方都是对称型 NAT),只能退而求其次走中继:数据绕一圈服务器转发,能用,但贵、也慢。视频通话软件里那套 STUN / TURN 机制,本质上就是在"直连打洞"和"中继兜底"之间做选择。

问题三:凭什么让我上传?

这是我觉得最妙的部分。BitTorrent 的规则是"以牙还牙(tit-for-tat)":

  • 你只愿意优先把数据传给我,我就优先把数据传给你;那些只下载、不上传的"吸血"客户端,会被所有人一起降速甚至掐断。
  • 同时还规定最稀有的块优先下载,避免某个冷门分片最后只剩一个人有、成为瓶颈。

一个没有任何中心管理的网络,靠一条简单的博弈规则,就让几百万个互不认识的陌生人愿意互相帮忙——这比"服务器很强大"有意思多了。

那它是不是好事?

技术上它中立,但用在哪里差别巨大。

好的那一面: 开源镜像分发(Linux 发行版至今仍靠 P2P 分担流量)、区块链、IPFS 这类内容寻址网络、局域网传文件、游戏联机、部分软件更新、WebRTC 视频通话,都是它的直系后代。抗审查也是它天生的属性——没有中心,就没有可以关掉的地方。

麻烦的那一面: 它同时也把"未经授权传播"的成本降到了极低,Napster 和海盗湾的官司就是这么来的;它还是僵尸网络(让被感染的机器互相指挥)和恶意文件传播的温床。另外,用户自己也在承受代价:上传占用你家宽带、暴露你的 IP、连接列表里可能混进坏节点。

有意思的是,正因为监管和版权压力,很多"民用 P2P"后来退回了局域网和加速器——我们能看到的 P2P,反而越来越"小"了。

我的一点感想

我最佩服的不是它"快",而是它把三个看起来很脏的问题(找谁、连不上、凭什么帮你)分别用哈希寻址、NAT 打洞、博弈激励解决掉了,而且没有一个是靠"加一台更强的服务器"。

如果要用一句话概括它的思想,我觉得是:把中心去掉,把规则留下。中心会挂、会被关、会变贵,规则只要大家都认,就能一直跑下去。

参考资料