emule学习与分析<一> 概述
话说在前
其实笔者都不怎么用电骡,对电骡的认识肯定不比一个下载爱好者的姿势高,所以有写的不对的地方欢迎指出
本文是为铺垫该系列文——实现一个支持ED2K协议的Java下载器 ,该系列会跟随我写的进度,也会比照对应一些我写的代码。
读者可以参考下面这位大哥整理的资料,怎么也该整理的比我好。
https://blog.csdn.net/huang_rong12/article/details/51277239
开始
本文将针对基于的ED2K网络的emule进行概述,服务于后续的emule客户端研究,参考工具为电骡客户端(emule),笔者使用的版本是v0.50a,强烈建议下载一个电骡把玩一番,更好理解
Emule下载地址:https://www.emule-project.net/home/perl/general.cgi?l=42&rm=download
1.白话向
提起ED2K大部分人第一反应肯定是那一串神秘代码,其实这个链接可以说是ED2K网络主要在做的事——文件共享(不仅仅是下载)。
那一串代码意思就是在描述你要下载的文件,要想下载就得有一个支持ED2K协议的客户端,并连接上ED2K网络,再去和服务器沟通一下谁在下这个文件(分片),然后服务器安排下你和XXX建立一个连接,他有这个文件(片段),然后你一边下载一边和再把文件(片段)分享给其他人,大家一起快乐起来了
2.EMULE是什么
电骡(eMule)是一个开源免费的P2P文件共享软件,基于eDonkey2000的eDonkey网络,遵循GNU通用公共许可证协议发布,运行于Windows下。eMule中文名称在大陆用户中有争议,根据eMule官方网站的简体中文版说法,“eMule”译为“电骡”,其名称也来源于动物:骡。
3.ED2K网络是什么?
ed2k也称eDonkey2000 Network是一种文件分享网络,与多数文件共享网络一样,它是分布式的;文件基于点对点原理传输,而不是由中枢服务器提供。
这里记住划重点,ed2k是一个P2P网络,但并没有完全去中心化(服务器仍存在)
概述(科学向)
可以看做emule协议指南的导论了
1.总体梗概
在 eMule 网络世界中,全球范围内数以百计的 eMule 服务器和成百上千万的 eMule 客户端导演着eMule的繁荣.客户端(Clients)为了得到eMule网络服务,需要与至少一个服务器(Server) 建立连接,这个与服务器的连接会在客户端整个生命周期内长期保持.在这个体系内,服务器提供集中的索引服务(如同 Napster),值得注意的是,服务器之间并不进行通信.
每个 eMule 客户端都中预设置有两个列表,其一包括服务器地址,另一个列表则包含了其本地文件系统中的共享文件.客户端与一个eMule服务器建立一个对应的TCP连接,从而登录网络并获取关于所需文件的信息,并获取用于找寻其他可联络的客户端的信息.于此相对 应,eMule 客户端为了实现与其他客户端间进行文件上传与下载,与这些客户端建立了数以百计的TCP连接.每个eMule客户端为它的每个共享文件都独立得维护一个上传有限队列.一个 待下载的客户端将会从这个队列底部加入,并逐步提升其在队列中的位置,直到这个它达到队 列顶部,就开始下载文件.一个客户端可以从多个不同客户端下载同一个文件,从每一个客户 端中下载文件的不同部分.同理,上传客户端也可以给待下载客户端上传文件的部分块,即便 上传客户端没有完成整个文件的下载.eMule 还扩展了 eDonkey 的性能,允许客户端之间交换 服务器信息和共享文件及其他客户端的相关信息.
值得注意的是,客户端-客户端通信和客户端-服务器通信都是基于 TCP 的. 服务器通过其数据库保存文件和客户端的信息,它并不保存任何共享文件,它只是为共享文件 的位置提供一个集中索引.服务器还有一个已经逐渐被放弃的功能,即为因有防火墙阻碍或其 他原因造成的无法接受进入连接的客户端(俗称 LowID 客户端)提供桥接服务.但是这种桥接 功能极大地增加了服务器的载荷.eMule 还使用 UDP 来提升客户端-服务器及客户端-客户端 连接的性能.但是,对于一个客户端是否能正确的传输和接受 UDP 报文并无强制性要求,也不 会影响到常规功能,即便防火墙禁止了 UDP 传输也可以无故障的运行 eMule.
只需划重点,一些lowID,UDP的东西没这么快接触到可选择性忽略
1、想要获取Emule网络支持,客户端必须和一个服务器保持连接(TCP),连接生命周期与客户端存在时间相同。
2、客户端维护一个下载文件列表和共享文件列表,通过文件信息向服务器查找其他客户端,服务器用数据库维护文件和客户端的信息(不直接提供文件),并提供给客户端,让他们进行点对点传输。
3、下载文件是分块的,所以客户端可以从其他多个客户端下载不同的块,也可以将共享文件的块上传给多个其他的客户端
2.客户端——服务器连接概述
客户端启动时,首先与一个 eMule 服务器建立 TCP 连接,服务器向其提供一个客户端 ID.客户端ID的生命周期等于其客户端-服务器连接的生命周期,对于HighID而言,所有的 服务器都会根据其IP计算一个固定的客户端ID,这点与LowID不同.(后文将会讲述lowID和HighID)
随着连接建立,客户端向 服务器上传它的共享文件列表,服务器将这个列表储存在数据库中,同时,客户端向服务器上传一个下载文件列表,其中包含了客户端需要下载的文件信息. 连接建立完毕后, eMule 服务器向这个客户端发送一个源列表,这个列表包含了拥有这个客户端待下载文件的其他客户端的信息.这种拥有别的客户端所需求的资源或文件的客户端就称作源.从这时起,这个客户端就开始与其他客户端建立连接. 这个客户端-服务器 TCP 连接在整个客户端会话过程中一直保持开启.
在初始的握手会话后, 客户端-服务器会话往往由客户端的某些活动所引起,比如客户端的文件搜索请求会引起服务器的文件搜索结果应答,在搜索会话之后,客户端会发起一个对特定文件的源查询请求,此 时,服务器会返回一个源列表(包括 IP 地址和端口号),客户端就可以使用这个列表上的信息下 载所查询的文件. 客户端-服务器 UDP 连接是客户端用于和其他未建立 TCP 连接服务器间建立通讯的.这种 UDP 通信的目的在于加强文件搜索和源搜索功能,并更高效的使用客户端所拥有的服务器信 息.
其实只是比上面的总体概述详细了些,技术细节尚在情理之中,这里只要
注意:拥有其他客户端需要资源的客户端被称作源,这个在后文讲LOWID和HIGHID的时候有用
3.客户端——客户端连接概述
eMule的客户端-客户端连接实现文件的共享,在共享过程中,文件被分为不同部分,每部分并 被细分为不同的块,一个客户端可以同时从多个不同的客户端处下载一个文件的不同部分. 当客户端-客户端连接建立后,两个客户端会进行传输性能信息交换,随后对上传或下载的开 始时间进行协调.每个客户端都会对发出下载请求的待下载客户端建立一个下载队列.当一个 eMule客户端的下载队列为空时,新的下载请求会立即开始下载会话,除非这个请求客户端被 源禁止.当这个下载队列非空时,新的下载请求就将请求客户端添加到下载队列底部.如果将传输带宽小值定为2.4kbytes/秒,一个客户端可同时进行的上传数通常不超过几个.在下载队列中,允许一个正在等待的客户端取代正在下载的客户端,这取决于他们的队列优先级别, 在一个客户端开始下载会话的十五分钟之内,它在下载队列中的优先级别会提高到高水平, 以防止频繁的下载竞争.
当一个待下载客户端到达下载队列顶部,上传客户端会在这两个客户端之间启动一个用于文 件传输的连接.一个eMule客户端可出现在多个源的待下载队列中,等待按部分从每个目标源 中下载文件.当客户端从其中一个源下载到文件的某些部分,这个下载客户端并不会告知所有 它在下载队列出现的源,并让它们删除这个下载客户端的请求.而是当其到达某个源的下载队 列顶部时,拒绝源的上传会话. eMule使用了一种鼓励上传的信用机制(见1.4节),为了防止针对这种机制的冒名欺诈,eMule使用RSA公钥算法.
客户端-客户端连接会用到一组不同于eDonkey协议中定义的报文,被称为扩展协议.扩展协议 提供一些增强服务,如信用机制的具体实现,增加的服务器和源列表更新功能,以及通过压缩 传输增强文件块传输的性能. eMule的客户端-客户端连接中的UDP使用较为局限,主要用于客户端在对列中等待开始下载 时,周期性地查询其在队列中的状态.
这部分骤然复杂了不少,不过短时间内还不需要了解到这么多技术细节,可以走的够远了再回过头再来看这部分
解惑
看完以上一大堆废话,肯定要对LOWID、HIGHID做一个解释
客户端ID是什么?
客户端ID是在客户端-服务器连接握手时由服务器提供的一组4字节辨识码.
客户端 ID 如何分配?
简单来说LOW ID和HIGH ID的区别就是,当服务器和你建立连接时会判定连接有没有受到干扰(主要判定是不是公网IP)。如果没有,即根据你的IP计算一个全ED2K服务器通用的ID授予给你(HIGHID),否则授予你一个LOWID(计算方法服务器决定,似乎是IP无关),LOWID生命周期和TCP连接相关,而HIGHID和IP相关。
那么LOW ID和HIGH ID用起来有啥区别?
服务器不会维护LOWID的IP地址,所以LOWID无法直接被其他的客户端连接,为了解决这个问题,emule提供回叫机制,源如果是LOWID,那么客户端启动回叫,让服务器把请求客户端的IP等信息发给源(因为服务器保持了一个和源的TCP连接),由源来发起客户端——客户端的连接.
注意:回叫增加了服务器的工作量,所以对服务器来说回叫不是好事。
详细信息
1.3 客户端 ID
客户端ID是在客户端-服务器连接握手时由服务器提供的一组4字节辨识码.
对于LowID而言, 这个客户端ID只在整个客户端-服务器TCP连接周期中有效;而对于HighID,客户端ID是由其 IP地址计算而来,只随IP的改变而改变.因此,客户端ID有HighID和LowID之分.典型的,eMule 服务器会给一个无法接收进入连接的客户端分配LowID.当一个客户端被分配LowID,将会在 eMule网络受到限制,并可能会因此引起服务器拒绝其连接.
对于HighID而言,其ID是经下文中 描述的方法由IP计算而得.此处的计算和重要性判断是基于一个eMule具体实现[3]的.被授予 HighID的客户端需要具备如下条件,即其他客户端可以自由地连接到这台主机的eMule TCP 端口(默认为4662端口). 被授予HighID的客户端在整个eMule网络中不受限制.然而,只要服务器无法在客户端的eMule的TCP端口建立连接,就会给其赋予一个LowID.所以,一个客户端会 因如下情况被赋予一个LowID:
主机防火墙阻止了连入连接.
客户端使用NAT或代理服务器连入网络.
服务器太忙(造成再连接计时器计时结束).
但是值得注意的是,LowID 的分配因服务器而异. 因为 LowID 没有相应的 IP 地址来建立客户端-客户端连接,所以,所有的通信需要 eMule 服务 器参与,这增加了服务器的负载同时也导致了服务器接收 LowID 客户端请求延迟.同时,这意 味着一个LowID客户端无法和在其他服务器上的另一个LowID客户端建立连接.因为eMule 不支持服务器间的通道连接.为了支持 LowID 客户端, eMule 引入了一种回叫机制.通过运用 这种机制,HighID 客户端可以通过服务器询问一个 LowID 客户端,从而发起一个连接,并实现 文件交换.
结束
其实网上相关资料很少,就算emule是开源的,源码分析也不算很多(主要我也看不懂C++)
笔者先讲到这里,对于理解后续文章基本够用了,故点到为止,后续可能会有所补充
如果有对emule知识,感兴趣的可以去百度emule贴吧里学习下
参考资料
eMule协议指南.pdf