FTP 的两种工作模式
FTP, 也即⽂件传输协议:FTP 采用两个 TCP 连接来传输一个文件:控制连接、数据连接。
从 FTP 服务器角度,FTP 有两种工作模式,分别是主动模式(PORT)和被动模式(PASV)
- 主动模式(PORT):客户端打开N和N+1两个端口(N>1024),N端口向服务器的命令端口 21 发起连接,N+1 端口监听,并向服务器发出 “port N+1” 命令,服务器从自己的数据端口 20,主动连接到客户端指定的数据端口 N+1。
- 被动模式(PASV):客户端打开N和N+1两个端口(N>1024),N端口连接服务器的 21 端口,提交 PASV 命令,服务器会开启一个任意的端口 P(> 1024),返回“227 entering passive mode”消息里面包含FTP 服务器开放的用来进行数据传输的端口。客户端收到消息取得端口号之后,会通过 N+1 号端口连接服务器的端口 P,然后在两个端口之间进行数据传输。
难以解决单一服务器的带宽压力, 因为使用的是传统的客户端服务器的方式。
P2P 是什么?
P2P就是peer-to-peer。资源并不集中地存储在某些设备上,而是分散地存储在多台设备上。这些设备姑且称为 peer。
下载文件时,需得到下载文件的peer,与之建立点对点连接,就近下载文件。下载文件后,自己成为peer的一员。
种子(.torrent)文件
通过种子,即.torrent文件,知道哪些peer有什么文件。
.torrent文件组成:announce(tracker URL)、文件信息。
文件信息:
- info 区:指定的该种子有几个文件、文件有多长、目录结构,以及目录和文件的名字。
- Name 字段:指定顶层目录名字。
- 每个段的大小:BitTorrent(简称 BT)协议把一个文件分成很多个小段,然后分段下载。
- 段哈希值:将整个种子中,每个段的 SHA-1 哈希值拼在一起。
下载过程:
- BT 客户端解析.torrent 文件,得到 tracker 地址,然后连接 tracker 服务器
racker 服务器 - 回应下载者的请求,将其他下载者(包括发布者)的 IP 提供给下载者
- 下载者再连接其他下载者,根据.torrent 文件,两者分别对方告知自己已经有的块,然后交换对方没有的数据。
- 下载者计算下载的每个块的Hash值,并与.torrent 文件中的对比。不一样则需要重新下载这个块
这种方式特别依赖 tracker。racker服务器登记有哪些应用请求哪些资源,一旦出现故障,BT工具无法工作。
去中心化网络(DHT)
为了彻底非中心,就有了一种叫作DHT(Distributed Hash Table)的去中心化网络。每个加入这个 DHT 网络的人,都要负责存储这个网络里的资源信息和其他成员的联系信息。一种著名的 DHT 协议,叫Kademlia 协议。
Kademlia 协议
可参看 :Kademlia
任何一个 BitTorrent 启动之后,它都有两个角色。一个是peer,另一个角色DHT node。
- peer:监听一个 TCP 端口,用来上传和下载文件。
- DHT node:监听一个 UDP 的端口,通过这个角色,这个节点加入了一个 DHT 的网络。
在 DHT 网络里面,每一个 DHT node 都有一个 ID。每个 DHT node 都有责任掌握一些知识,也就是文件索引,知道某些文件是保存在哪些节点上,本身不一定就是保存这个文件的节点。
哈希值
每个 DHT node 不会有全局的知识,不知道所有的文件保存在哪里,只需要知道一部分。
DHT node 上应该有哪些文件的位置信息?
每个文件可以计算出一个哈希值,而DHT node 的 ID 是和哈希值相同长度的串。
DHT 算法是这样规定的:如果一个文件计算出一个哈希值,则和这个哈希值一样的那个 DHT node,就有责任知道从哪里下载这个文件,即便它自己没保存这个文件。除了一模一样的那个 DHT node 应该知道,ID 和这个哈希值非常接近的 N 个 DHT node 也应该知道。
例子如上面的图: 文件 1 通过哈希运算,得到匹配 ID 的 DHT node 为 node C,node C 有责任知道文件 1 的存放地址,虽然 node C 本身没有存放文件 1。文件 2 通过哈希运算,得到匹配 ID 的 DHT node 为 node E,node D 和 E 的 ID 值很近,所以 node D 也知道。
新的节点 node new 如果想下载文件 1,它首先要加入 DHT 网络。
新的节点 node new如何加入DHT 网络
种子.torrent中保存的不再是tracker的地址,而是一个node地址的list(去中心化),只要与其中一个联系上便加入了网络。
新的节点 node new如何下载文件 1
node new 会计算文件 1 的哈希值,根据这个哈希值了解到哪些node知道从哪可以下载到这个文件。例如计算出来的哈希值就是 node C。
node new但是如何联系node C?
种子里面的 node 列表里面很可能没有 node C,但是它可以它能联系上的 node 问,node new 想联系 node C,就去像去万能的朋友圈问,并且求转发,朋友再问朋友,很快就能找到。如果找不到 C,也能找到和 C 的 ID 很像的节点,它们也知道如何下载文件 1。
在 node C 上,告诉 node new,下载文件 1,要去 B、D、 F,于是 node new 选择和 node B 进行 peer 连接,开始下载,它一旦开始下载,自己本地也有文件 1 了,于是 node new 告诉 node C 以及和 node C 的 ID 很像的那些节点,我也有文件 1 了,可以加入那个文件拥有者列表了。
DHT node ID 以及文件哈希是个什么东西?
节点 ID 是一个随机选择的 160bits(20 字节)空间,文件的哈希也使用这样的 160bits 空间。
所谓 ID 相似,具体到什么程度算相似?
在 Kademlia 网络中,距离是通过异或(XOR)计算的。例如01010 与 01000 的距离,就是两个 ID 之间的异或值,为 00010,也即为 2。 01010 与 00010 的距离为 01000,也即为 8。
高位不同的,表示距离更远一些;低位不同的,表示距离更近一些,总的距离为所有的不同的位的距离之和。
这个距离不能比喻为地理位置,因为在 Kademlia 网络中,位置近不算近,ID 近才算近。
DHT 网络中的朋友圈是怎么维护的?
按距离分层。对于某个基础节点node,将与之从倒数第 i 位开始不同的节点放入“k-bucket i”,k-bucket i 内只有 个节点,与node的距离范围为 。
DHT 网络是如何查找朋友的?
node A 要找 node B,两者异或距离为10110,范围在 , 所以 node B 可能在 node A 的 ”k-bucket 5“中,两者从第5位开始不同。
A 发现自己的 k-bucket 5 中没有 B,于是在 k-bucket 5 中随便找了一个,假如是C,既然 C 与 A 的第5位不同,那么肯定与 B 的第5位相同,即 C 与 B 的距离 ,距离缩短了一半以上。C 再继续查找即可,时间复杂度位 。
在 DHT 网络中,朋友之间怎么沟通呢?
Kademlia 算法中,每个节点只有 4 个指令。
- PING:测试一个节点是否在线
- STORE:要求一个节点存储一份数据,既然加入了组织,有义务保存一份数据。
- FIND_NODE:根据节点 ID 查找一个节点
- FIND_VALUE:根据 KEY 查找一个数据,实则上跟 FIND_NODE 非常类似。
DHT 网络中,朋友圈如何更新呢?
- 每个 bucket 里的节点,都按最后一次接触的时间倒序排列。
- 每次执行四个指令中的任意一个都会触发更新。
- 当一个新节点与自己接触时,如果在 k-bucket 中,则置顶;不在,若通讯录满,最旧的节点能 PING 通,则丢弃新节点;PING 不同,则删除旧节点,加入新节点。
参考资料:
趣谈网络协议(极客时间)链接:
http://gk.link/a/106nW
Kademlia:
https://zh.wikipedia.org/wiki/Kademlia
https://en.wikipedia.org/wiki/Kademlia
P2P之Kademlia (一):
https://blog.csdn.net/cz_hyf/article/details/5076988
P2P之Kademlia (二):
https://blog.csdn.net/cz_hyf/article/details/5178330
GitHub链接:
https://github.com/lichangke/LeetCode
知乎个人首页:
https://www.zhihu.com/people/lichangke/
CSDN首页:
https://me.csdn.net/leacock1991
欢迎大家来一起交流学习