emule源代碼分析_第1頁(yè)
已閱讀1頁(yè),還剩46頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、<p><b>  轉(zhuǎn)自中國(guó)源碼網(wǎng)</b></p><p>  eMule的官方首頁(yè)上寫(xiě)著:2002年05月13日 一個(gè)叫做 Merkur 的人,他不滿意原始eDonkey2000客戶端并且堅(jiān)信他能夠做的更好,所以他開(kāi)始制作。他聚集了其它開(kāi)發(fā)人員在他的周圍,并且eMule工程就此誕生。eMule是一個(gè)典型的MFC程序,它的圖形界面等,已經(jīng)和MFC緊緊融合到了一起。因此通常情況下

2、它只能在windows平臺(tái)下運(yùn)行。有一些其它的工程,如aMule等,把它進(jìn)行了移植,因此跨平臺(tái)的功能要強(qiáng)些。其實(shí)還有另外一個(gè)叫做xMule的工程,不過(guò)現(xiàn)在已經(jīng)人氣快不行了。在aMule的主頁(yè)上可以看到eMule移植到linux平臺(tái)下的一些歷史,最早是有個(gè)叫做lMule的工程,他使用wxwidgets來(lái)進(jìn)行eMule的跨平臺(tái)的移植,這個(gè)工程2003年就不再更新了,后來(lái)轉(zhuǎn)變成為xMule工程,它一度是linux平臺(tái)下eMule的事實(shí)上的

3、替代品。但是他們的程序員之間由于理念不同,發(fā)生了內(nèi)訌,導(dǎo)致aMule分裂出來(lái),他們后來(lái)矛盾嚴(yán)重的時(shí)候曾經(jīng)一度從理念問(wèn)題上升到互相對(duì)對(duì)方進(jìn)行人身攻擊,并且曾經(jīng)對(duì)對(duì)方的網(wǎng)站發(fā)動(dòng)過(guò)DDos。后來(lái)aMule和xMule就是兩個(gè)完全不同的工程,xMu</p><p>  eMule的代碼結(jié)構(gòu)非常合理。雖然代碼量比較大,但是各個(gè)功能模塊之間的劃分都很合理。從它的工程文件里面就可以看出這一點(diǎn)。eMule把表示功能的代碼文件和表

4、示界面的代碼文件分開(kāi)了,Source Files和Header Files是實(shí)現(xiàn)功能的代碼的源文件和頭文件,而Interface Source和Interface Header是實(shí)現(xiàn)圖形界面的源文件和頭文件。由于eMule的代碼量太大,本系列將跳過(guò)圖形界面的實(shí)現(xiàn),著重分析eMule的功能實(shí)現(xiàn)部分的代碼,而且功能實(shí)現(xiàn)方面也主要挑主要的部分分析。本節(jié)將從emule.cpp開(kāi)始分析,引出eMule中使用到的幾個(gè)主要的功能實(shí)現(xiàn)的類,并大體描述它

5、們的作用。最后介紹一下如何在VS2003下編譯eMule。emule中還有不少模塊實(shí)現(xiàn)的功能挺有用,我說(shuō)的是在其它的程序里很有用,可以考慮在其它程序中進(jìn)行復(fù)用。emule.cpp為類CemuleApp的實(shí)現(xiàn)。因此在運(yùn)行時(shí),首先會(huì)運(yùn)行InitInstance進(jìn)行一些初始化的工作。從這個(gè)函數(shù)里面我們也可以第一次看出那些即將在整個(gè)程序中發(fā)揮作用的類了。最開(kāi)始的時(shí)候是計(jì)算出程序常用的一些目錄,如配置文件</p><p

6、>  eMule中要讀取的配置文件數(shù)量較多,每種配置文件都是自己定義的格式,為了方便讀取和存儲(chǔ)這些文件,eMule中有一個(gè)很重要的基礎(chǔ)設(shè)施類來(lái)復(fù)制這些文件操作,它能夠很方便得處理一些常用數(shù)據(jù)類型的讀寫(xiě),并且?guī)в幸欢ǖ陌踩Wo(hù)機(jī)制。這項(xiàng)基礎(chǔ)設(shè)施在SafeFile.cpp和SafeFile.h中實(shí)現(xiàn)。在kademlia\io目錄下有這項(xiàng)功能的另外一項(xiàng)實(shí)現(xiàn)。它們實(shí)現(xiàn)的功能基本上相似,但是kademlia\io目錄下的版本實(shí)現(xiàn)的時(shí)候多了一

7、個(gè)以Tag作為單位進(jìn)行讀寫(xiě)的功能。這些實(shí)現(xiàn)中和另外一項(xiàng)基礎(chǔ)設(shè)施,那就是字符串轉(zhuǎn)化密切相關(guān)。StringConversion.cpp和StringConversion.h是eMule中專門(mén)復(fù)制各類字符串轉(zhuǎn)化的基礎(chǔ)設(shè)施,什么Unicode啊,多字節(jié)流啊,或者是UTF-8之類的,在這里轉(zhuǎn)化全部都不是問(wèn)題。關(guān)于字符串轉(zhuǎn)化,個(gè)人推薦盡量使用Unicode的寬字符,這樣可以最大程度得避免亂碼。SafeFile.cpp或者kademlia\io目

8、錄下的實(shí)現(xiàn)都有這樣的特點(diǎn),那就是把數(shù)據(jù)操作的行為和數(shù)據(jù)操作的對(duì)象分割開(kāi)來(lái)。它們都定義了一個(gè)抽象的數(shù)據(jù)操作的基類(在SafeFile.</p><p>  emule作為一個(gè)文件共享方面的程序,首先要對(duì)自己共享的所有的文件的信息都十分清楚,類CKnownFileList的作用就是這樣的,它在emule.cpp中隨著cmuleapp類創(chuàng)建的時(shí)候被創(chuàng)建。CKnownFileList類使用了MFC的CMap類來(lái)維護(hù)內(nèi)

9、部的hash表,這也可以看出emule和MFC的關(guān)系確實(shí)非常緊密。這里如果用STL的map其實(shí)也是可以的。它內(nèi)部維護(hù)了一個(gè)已知的文件的列表和取消了的文件列表。這些hash表的關(guān)鍵字都是文件的hash值。這樣能夠判斷出文件名不同而內(nèi)容相同的文件,而一般要讓不同內(nèi)容的文件有相同的hash值是非常困難的,這也是hash函數(shù)它設(shè)計(jì)的初衷。因此除非是碰上王小云教授這樣的牛人,我們基本上可以認(rèn)為,兩個(gè)文件hash值相同就代表了它們內(nèi)容相同。再來(lái)看C

10、KnownFileList.cpp,這個(gè)文件其實(shí)并不長(zhǎng),因?yàn)楣芾硪粋€(gè)列表確實(shí)不需要太多種類的操作,如果對(duì)于每個(gè)具體的文件有一個(gè)很強(qiáng)大的類來(lái)處理它的話。而這里確實(shí)有,它就是CKnownFile。有了這么一個(gè)類,我們就可以看到,CKnownFileList類所需要做的工作就是能夠根據(jù)一些信息查找到對(duì)應(yīng)</p><p>  eMule源代碼解析 -2 2006-10-16 17:4</p><p&g

11、t;  1分塊機(jī)制--正確傳輸資源的保證 為了加快內(nèi)容分發(fā)的速度,分塊處理是一種簡(jiǎn)單有效的方法。emule中對(duì)每個(gè)文件都進(jìn)行了分塊處理。另外分塊還有一個(gè)好處就是如果保留了每一分塊的hash值,就能在只下載到文件的一部分時(shí)判斷出下載內(nèi)容的有效性。</p><p>  emule在獲取每個(gè)共享文件的信息時(shí),就對(duì)它進(jìn)行了分塊處理,因此如果要知道emule中的分塊處理和恢復(fù)機(jī)制,看CKnownFile::CreateFr

12、omFile函數(shù)的實(shí)現(xiàn)就行了。 </p><p>  這個(gè)函數(shù)中牽涉到的和分塊處理以及hash計(jì)算相關(guān)的類都在SHAHashSet.cpp和SHAHashSet.h中。</p><p>  下面介紹其中幾個(gè)主要的類:</p><p>  CAICHHash類只負(fù)責(zé)一塊hash值,提供兩個(gè)CAICHHash類之間的直接賦值,比較等基本操作。CAICHHashAlgo是

13、一個(gè)hash算法的通用的接口,其它hash算法只要實(shí)現(xiàn)這種接口都能使用,這樣,可以很方便得使用不同的hash算法來(lái)計(jì)算hash值。CAICHHashTree則是一個(gè)樹(shù)狀的hash值組織方式,它有一個(gè)左子樹(shù)和右子樹(shù)成員變量,類型是指向CAICHHashTree的指針,這是一個(gè)典型的實(shí)現(xiàn)樹(shù)狀結(jié)構(gòu)的方法。CAICHHashSet中包含了一個(gè)CAICHHashTree類型的變量,它直接向CKnownFile負(fù)責(zé),代表的是一個(gè)文件的分塊信息。 S

14、HAHashSet.h文件的開(kāi)始的注釋部分向我們解釋了它的分塊的方式。這里要用到兩個(gè)常量9728000和184320,它們分別是9500k和180k。這是emule中兩種不同粒度的分塊方式,即首先把一個(gè)很大的文件分割成若干個(gè)9500k的塊,把這些塊組織成一顆樹(shù)狀的結(jié)構(gòu),然后每一個(gè)這樣的塊又分解成若干個(gè)180k的塊(52塊,再加一個(gè)140k的塊),仍然按照樹(shù)狀的結(jié)構(gòu)組織起來(lái)。最后總的結(jié)構(gòu)還是一顆樹(shù)。 CKnownFile::Cr</

15、p><p>  最后我們還需要注意的就是CKnownFile類中的hashlist變量。就是說(shuō)它還單獨(dú)保留直接以9728000字節(jié)為單位的所有分塊的MD4算法的hash值。這樣對(duì)于一個(gè)文件就有了兩套分塊驗(yàn)證的機(jī)制,能夠適應(yīng)不同場(chǎng)合 網(wǎng)絡(luò)基礎(chǔ)設(shè)施--網(wǎng)絡(luò)基礎(chǔ)設(shè)施的基礎(chǔ)設(shè)施 MFC中已經(jīng)有一些網(wǎng)絡(luò)基礎(chǔ)設(shè)施類,如CAsyncSocket等。但是emule在設(shè)計(jì)中,為了能夠更加高效得開(kāi)發(fā)網(wǎng)絡(luò)相關(guān)的代碼,構(gòu)建了另外的一些類作為

16、基礎(chǔ)設(shè)施,這些基礎(chǔ)設(shè)施類的代碼也有很高的復(fù)用價(jià)值。</p><p>  首先是CAsyncSocketEx類。AsyncSocketEx.h中對(duì)這個(gè)類的特點(diǎn)已經(jīng)給出了一定的說(shuō)明。它完全兼容CAsyncSocket類,即把應(yīng)用程序中所以的CAsyncSocket換成CAsyncSocketEx,程序仍然能夠和原來(lái)的功能相同,因此在使用上更加方便。但是在這個(gè)基礎(chǔ)上,它的效率更高,主要是在消息分發(fā)機(jī)制上,即它處理和SO

17、CKET相關(guān)的消息的效率要比原始的MFC的CAsyncSocket類更高。</p><p>  另外,CAsyncSocketEx類支持通過(guò)實(shí)現(xiàn)CAsyncSocketExLayer類的方式,將一個(gè)SOCKET分成若干個(gè)層,從而可以很方便得實(shí)現(xiàn)許多網(wǎng)絡(luò)功能,如設(shè)置代理,或者是使用SSL進(jìn)行加密等。 </p><p>  另外還有ThrottledSocket.h中定義的ThrottledC

18、ontrolSocket類和ThrottledFileSocket類,這兩個(gè)類只定義了兩個(gè)接口。任何其它的網(wǎng)絡(luò)套接字類如果想實(shí)現(xiàn)限速的功能,只需要在其默認(rèn)的發(fā)送函數(shù)(如Send或Sendto)中不發(fā)送數(shù)據(jù)而是把數(shù)據(jù)緩存起來(lái),然后在實(shí)現(xiàn)ThrottledControlSocket或者ThrottledFileSocket接口中的SendFileAndControlData或SendControlData方法時(shí)才真正把數(shù)據(jù)發(fā)送出去,這樣就能

19、實(shí)現(xiàn)上傳限速,而這也是需要UploadBandwidthThrottler類進(jìn)行配合,UploadBandwidthThrottler是一個(gè)WinThread的子類,平時(shí)單獨(dú)運(yùn)行一個(gè)線程。下一次會(huì)詳細(xì)描述它是如何控制全局的上傳速度的。 網(wǎng)絡(luò)基礎(chǔ)設(shè)施--全局限速器UploadBandwidthThrottler UploadBandwidthThrottler是emule中使用的全局的上傳限速器。它繼承了CWinThread類,且在該類被

20、創(chuàng)建的時(shí)候,就新創(chuàng)建一個(gè)線程開(kāi)始單獨(dú)運(yùn)行。在該類被</p><p>  而其它四個(gè)隊(duì)列都是實(shí)現(xiàn)ThrottledControlSocket接口的類的隊(duì)列,在這些隊(duì)列中的類主要以傳輸控制信息為主。</p><p>  這四個(gè)隊(duì)列為臨時(shí)高優(yōu)先級(jí),臨時(shí)普通優(yōu)先級(jí),正式高優(yōu)先級(jí),正式普通優(yōu)先級(jí)。和把套件字直接添加到普通隊(duì)列(AddToStandardList)不同,</p><

21、p>  QueueForSendingControlPacket把要添加到隊(duì)列的套接字全部添加到兩個(gè)臨時(shí)隊(duì)列。根據(jù)它們的優(yōu)先級(jí)添加到普通的臨時(shí)隊(duì)列。在RunInternal的大循環(huán)中,臨時(shí)隊(duì)列中的項(xiàng)目先被移到普通隊(duì)列中,然后再進(jìn)行處理。 </p><p>  UploadBandwidthThrottler使用了兩個(gè)臨界區(qū),兩個(gè)事件。pauseEvent是用來(lái)暫停整個(gè)大循環(huán)的動(dòng)作的。而threadEnded

22、Event是標(biāo)志整個(gè)線程停止的事件。sendLocker是大循環(huán)中使用的主要的臨界區(qū),而tempQueueLocker是為兩個(gè)臨時(shí)隊(duì)列額外添加的鎖,這樣可以一邊發(fā)送已有隊(duì)列中的套界字要發(fā)送的數(shù)據(jù),一邊把新的套接字加到隊(duì)列中。 </p><p>  UploadBandwidthThrottler的RunInternal中的大循環(huán)是該工作線程的日常操作。這個(gè)大循環(huán)中做了以下事情,計(jì)算本次配額,即本次循環(huán)中能夠發(fā)送多

23、少字節(jié),好安排調(diào)度,計(jì)算本次循環(huán)應(yīng)該睡眠多少時(shí)間,然后進(jìn)行相應(yīng)的睡眠,從而進(jìn)行限速。操作控制信息隊(duì)列,發(fā)送該隊(duì)列中的數(shù)據(jù),注意,控制隊(duì)列中的套接字(m_ControlQueueFirst_list和m_ControlQueue_list)只使用一次就離開(kāi)隊(duì)列。而標(biāo)準(zhǔn)隊(duì)列中的套接字不會(huì)這樣。在一輪循環(huán)結(jié)束后,如果還有沒(méi)有用完的發(fā)送數(shù)據(jù)的配額,則會(huì)有部分配額保存到下一輪。 網(wǎng)絡(luò)基礎(chǔ)設(shè)施--emule套接字CEMSocket CEMSocke

24、t是CAsyncSocketEx和ThrottledFileSocket的子類,它把若干功能整合到了一起,因此可以作為emule使用起來(lái)比較方便的套接字。例如它可以很方便得指定代理,把CAsyncSocketEx中的創(chuàng)建一個(gè)新的代理層并且添加到列表中的功能對(duì)外屏蔽了。另外它可以分出狀態(tài),如當(dāng)前是否在發(fā)送控制信息等。</p><p>  CEMSocket中我們需要仔細(xì)考察的是它的SendControlData和S

25、endFileAndControlData方法。如前所述,這些方法是用來(lái)和UploadBandwidthThrottler進(jìn)行配合,以便完成全局的限速功能的。它的功能應(yīng)該是按照UploadBandwidthThrottler的要求,在本次輪到它發(fā)送數(shù)據(jù)時(shí)發(fā)送指定數(shù)量的字節(jié)數(shù)。因此,應(yīng)用程序的其它部分在使用CEMSocket時(shí),如果要達(dá)到上傳數(shù)據(jù)限速的目的,不應(yīng)該直接調(diào)用標(biāo)準(zhǔn)的Send或者SendTo方法,而是調(diào)用SendPacket。這

26、里就有了另外一個(gè)結(jié)構(gòu)Packet,它通常包含一個(gè)emule協(xié)議中完整的包,例如有協(xié)議的頭部數(shù)據(jù)等,還內(nèi)置了PackPacket和UnPackPacket方法,可以自行進(jìn)行壓縮和解壓的功能。SendPacket把要發(fā)送的Packet放到自己的隊(duì)列中,這個(gè)隊(duì)列也有兩個(gè),控制信息包隊(duì)列,和標(biāo)準(zhǔn)信息包隊(duì)列。如果有必要,把自己加入到UploadBandwidthThrottler的隊(duì)列中。 我們注意到CEMSocket的SendControlDa

27、ta和SendFileAndControl</p><p>  eMule源代碼解析 -3</p><p>  2006-10-16 17:43</p><p>  搜索信息集-CSearchList</p><p>  CSearchList是emule中的搜索列表,掌管emule中所有的搜索請(qǐng)求。CSearchFile是這個(gè)列表中的元素,

28、代表了一次搜索的相關(guān)信息。它們的關(guān)系和之前描述的已知文件和已知文件列表有一些類似的地方。CSearchList的主要任務(wù)就是對(duì)其一個(gè)叫做list的類型為CSearchFile列表的內(nèi)部變量進(jìn)行維護(hù),提供很方便得往這個(gè)列表中添加,刪除,查詢,變更等操作的接口。另外,每一個(gè)搜索都有一個(gè)ID,是一個(gè)32位的整數(shù)。CSearchList中記錄了每個(gè)搜索目前搜到的文件個(gè)數(shù)和源的個(gè)數(shù)(m_foundFilesCount和m_foundSources

29、Count)。CSearchFile是CAbstractFile的另一個(gè)子類(CKnownFile也是),它保存了某個(gè)文件和搜索相關(guān)的信息,而不是這個(gè)文件本身的信息(這些信息在CAbstractFile中已經(jīng)包括了),這些和搜索有關(guān)的信息就是都在哪些機(jī)器上有這個(gè)文件,以及哪個(gè)服務(wù)器上搜到的這個(gè)文件。甚至還可以向搜索文件添加預(yù)覽。在這個(gè)類的定義中嵌套定義了兩個(gè)簡(jiǎn)單的結(jié)構(gòu)SServer和SClient,表示了該搜索文件的可能來(lái)源,服務(wù)&

30、lt;/p><p>  服務(wù)器信息集-CServerL</p><p>  盡管目前有了Kad網(wǎng)絡(luò),但是使用服務(wù)器來(lái)獲取各個(gè)emule用戶的共享文件列表仍然是emule中主要的資源獲取方式。CServerList就是emule中負(fù)責(zé)管理服務(wù)器列表的類。和前面若干列表類結(jié)構(gòu)類似,CServerList需要對(duì)外提供列表的增加,刪除,查找,修改等接口。在CServerList中,每個(gè)服務(wù)器的信息是一

31、個(gè)CServer類。和搜索信息不一樣,但是和已知文件列表一樣,服務(wù)器的信息列表是需要長(zhǎng)期保留的,因此CServerList和CKnownFileList類一樣提供了把它所包含的所有信息保存到一個(gè)文件中,以及從這個(gè)文件中讀回其信息的功能。CServer中的結(jié)構(gòu)比較簡(jiǎn)單,只需要保留服務(wù)器的各種信息即可。它可以通過(guò)IP地址和端口來(lái)創(chuàng)建,也可以通過(guò)一個(gè)簡(jiǎn)單的結(jié)構(gòu)ServerMet_Struct來(lái)創(chuàng)建,其中后者是用來(lái)直接從文件中讀取的。該結(jié)構(gòu)

32、僅僅包含IP地址和端口以及屬性的個(gè)數(shù),CServer中其它的屬性在保存到文件中時(shí),均采用Tag方式保存。CServerList除了提供通常的CServer信息外,還提供一些統(tǒng)計(jì)信息諸如所有的服務(wù)器的用戶數(shù),共享的文件數(shù)等。這些統(tǒng)計(jì)信息也</p><p>  emule的通信協(xié)議-一些基本的約定</p><p>  接下來(lái)將不可避免得要碰到emule的協(xié)議。emule的通信協(xié)議格式設(shè)計(jì)成

33、一種便于擴(kuò)充的格式。對(duì)于TCP連接來(lái)說(shuō),連接中的數(shù)據(jù)流都能夠劃分成為一個(gè)一個(gè)的Packet,CEMSocket類中就完成了把接收到的數(shù)據(jù)劃分成Packet這一工作。但是具體的對(duì)于每個(gè)Packet進(jìn)行處理的工作被轉(zhuǎn)移到它的子類中進(jìn)行。CEMSocket類的兩個(gè)子類CServerSocket和CClientReqSocket所代表的TCP連接就分別是客戶端和服務(wù)器之間的TCP連接以及客戶端之間的TCP連接。在數(shù)據(jù)流中的第一個(gè)字節(jié)代表的是通信

34、的協(xié)議簇代碼,如0xE3為標(biāo)準(zhǔn)的edonkey協(xié)議,0xE4為kademlia協(xié)議等等。接下來(lái)的四個(gè)字節(jié)代表包內(nèi)容的長(zhǎng)度,所有的包都用這種方式發(fā)送到TCP流中,就可以區(qū)分出來(lái)了。另外每個(gè)包內(nèi)容中的第一個(gè)字節(jié)為opcode,即在確定了某個(gè)具體協(xié)議后,這個(gè)opcode確定了這個(gè)包的具體含義。對(duì)于走UDP協(xié)議的包,處理起來(lái)更加得簡(jiǎn)單,因?yàn)閁DP本來(lái)就是以一個(gè)包一個(gè)包作為單位在網(wǎng)絡(luò)上流傳的,因此不需要在包的內(nèi)容中再包含表示長(zhǎng)度的字段。每個(gè)

35、UDP包的第一個(gè)字節(jié)是協(xié)議簇代碼,其它內(nèi)容就是包</p><p>  emule的通信協(xié)議-客戶端和服務(wù)器之間的通信概述</p><p>  客戶端和服務(wù)器之間的所有通信由類CServerConnect掌握。CServerConnect本身不是套接字的子類,但是它的成員變量CServerSocket類型的connectedsocket是。CServerConnect內(nèi)部有一列表,可以保存若

36、干CServerSocket類型的指針。但是這并不說(shuō)明它平時(shí)連接到很多服務(wù)器上。它只是可以同時(shí)試圖連接到若干個(gè)服務(wù)器上,這只是因?yàn)檫B接到服務(wù)器上的行為不一定能成功。CServerSocket類是CEMSocket的子類,它比CEMSocket要多保存一些狀態(tài),比如當(dāng)前的服務(wù)器連接狀態(tài)。它同時(shí)還保留它當(dāng)前所連接的服務(wù)器的信息。通過(guò)分析CServerSocket::ProcessPacket就可以直接把emule客戶端和服務(wù)器之間的通信

37、協(xié)議理解清楚,這里是服務(wù)器發(fā)回的包。TCP連接建立后的第一個(gè)包是在CServerConnect::ConnectionEstablished中發(fā)出的,即向服務(wù)器發(fā)出登陸信息。如果登陸成功,則能夠從服務(wù)器處獲取自己的ID,這是一個(gè)32位的長(zhǎng)整數(shù)。如果這個(gè)數(shù)小于16777216,那么我們稱它為L(zhǎng)owID。具有Lo</p><p>  emule的通信協(xié)議-客戶端和客戶端之間的通信概述</p><p

38、>  客戶端和客戶端之間的TCP通信由CListenSocket和CClientReqSocket完成。這也是提供網(wǎng)絡(luò)服務(wù)的應(yīng)用程序的典型寫(xiě)法。其中CListenSocket只是CAsyncSocketEx的子類,只負(fù)責(zé)監(jiān)聽(tīng)某個(gè)TCP端口。它只是內(nèi)部有一個(gè)CClientReqSocket類的列表。而CClientReqSocket是CEMSocket的子類,因此它能夠自動(dòng)完成emule的packet識(shí)別工作。它有ProcessPa

39、cket和ProcessExtPacket來(lái)處理客戶端和客戶端之間的包,其中前者是經(jīng)典的eDonkey協(xié)議的包,后者是emule擴(kuò)展協(xié)議的包。CListenSocket和CClientReqSocket類之間的關(guān)系和前面分析的列表類和它對(duì)應(yīng)的成員類的關(guān)系是相似的,CListenSocket提供對(duì)自身的CClientReqSocket列表中的元素的增加,查詢,刪除等操作。同時(shí)也維護(hù)關(guān)于這些成員的一些統(tǒng)計(jì)信息。我們注意到CListenS

40、ocket在其構(gòu)造函數(shù)中就把自己添加到CListenSocket類(theApp.listensocket,該類的唯一實(shí)際示例)的列</p><p>  eMule源代碼解析 -4</p><p>  2006-10-16 17:49</p><p>  emule中的信譽(yù)機(jī)制</p><p>  信譽(yù)機(jī)制在P2P系統(tǒng)中有非常重要的作用。為了

41、使用戶更加愿意共享自己的資源,需要有一些機(jī)制能夠讓對(duì)整個(gè)P2P系統(tǒng)貢獻(xiàn)更大的用戶有更多的激勵(lì)。在emule中,激勵(lì)機(jī)制的設(shè)計(jì)方案是tit-for-tat這種最直觀的方案。這種方案的意義就是最簡(jiǎn)單的如果別人對(duì)你好,那么你也對(duì)別人好。下面看實(shí)際的實(shí)現(xiàn)。CClientCreditsList和CClientCredits類負(fù)責(zé)emule中的信譽(yù)機(jī)制。我們?cè)俅我?jiàn)到這種列表和元素之間的關(guān)系,不必再重復(fù)那些語(yǔ)言。和信譽(yù)相關(guān)的信息是需要永久保存的,

42、這樣才有意義,因此CClientCreditsList提供了LoadList和SaveList方法。我們另外注意到,CClientCredits類可以使用CreditStruct結(jié)構(gòu)來(lái)創(chuàng)建,而CreditStruct結(jié)構(gòu)只包含靜態(tài)信息。主要是上傳量和下載量等。信譽(yù)機(jī)制的信息需要有一定的可靠性,在emule中采用了數(shù)字簽名的方式來(lái)做到這一點(diǎn)。Crypto++庫(kù)為emule全程提供和數(shù)字簽名驗(yàn)證相關(guān)的功能。CClientCreditsL

43、ist在創(chuàng)建時(shí),會(huì)裝載自己的公鑰私鑰,如果沒(méi)有的話,會(huì)創(chuàng)建一對(duì)。CClien</p><p>  下載任務(wù)即部分文件的表示</p><p>  CPartFile類是emule中用來(lái)表示一個(gè)下載任務(wù)的類。從它的名字也可以看出來(lái),這就是一個(gè)還沒(méi)有完成的文件。當(dāng)一個(gè)下載任務(wù)被創(chuàng)建時(shí),emule會(huì)在下載目錄中創(chuàng)建兩個(gè)文件,以三位數(shù)字加后綴part的文件,例如001.part,002.part等。

44、還有一個(gè)以同樣的數(shù)字加上.part.met的文件,表示的是對(duì)應(yīng)文件的元信息。part文件會(huì)創(chuàng)建得和原始文件大小一樣,當(dāng)下載完成后,文件名會(huì)修改成它本來(lái)的名稱。而事實(shí)上,諸如這個(gè)文件原來(lái)叫什么名稱,修改日期等等信息都在對(duì)應(yīng)的.part.met元文件中。.part.met中還包含了該文件中那些部分已經(jīng)下載完成的信息。CPartFile類中Gap_Struct來(lái)表示文件的下載情況,一個(gè)Gap_Struct就是一個(gè)坑,它表示該文件從多少字節(jié)

45、的偏移到多少字節(jié)偏移是一個(gè)坑。下載的過(guò)程就是一個(gè)不斷填坑的過(guò)程。CPartFile類中有個(gè)成員變量gaplist就是該文件目前的坑的狀況列表。需要主要的是有時(shí)填了坑的中間部分后,會(huì)把一個(gè)坑變成兩個(gè)坑??拥牧斜硪矔?huì)被存進(jìn).part.met中。CPartFile類的代碼很龐大,但是這是必須的。首先,它的創(chuàng)建就有</p><p><b>  下載任務(wù)隊(duì)列</b></p><

46、p>  CDownloadQueue是下載隊(duì)列類。這個(gè)隊(duì)列中的項(xiàng)目是CPartFile指針。因此和emule中出現(xiàn)的很多其它的列表類一樣,它需要能夠提供對(duì)這個(gè)列表中的元素進(jìn)行增加,查詢,刪除的功能。例如查詢的時(shí)候能夠根據(jù)該文件的hashID或者索引來(lái)進(jìn)行查詢。CDownloadQueue同時(shí)還要完成一些統(tǒng)計(jì)工作。和其它的列表類不一樣的是,它的所有元素的信息并不是集中存放于一個(gè)文件,而是對(duì)應(yīng)于每一個(gè)下載任務(wù),單獨(dú)得存放在一個(gè)元信

47、息文件(.part.met)中,因此當(dāng)該類進(jìn)行初始化的時(shí)候,它需要尋找所有可能的下載路徑,從那些路徑中找到所有的.part.met文件,并且試圖用這些文件來(lái)生成CPartFile類,并且將這些通過(guò).part.met文件正確生成的CPartFile類添加到自己的列表中,同樣,在退出時(shí),所有的下載任務(wù)的元信息也是自行保存,不會(huì)合成為一個(gè)文件。CDownloadQueue中的Process方法的主要任務(wù)就是把它的列表中的CPartFile

48、類中的Process方法都調(diào)一遍,另外主要的一些關(guān)于下載情況的統(tǒng)計(jì)信息也是在每一輪的Process后進(jìn)行更新的。從這里我們也可以看出P</p><p><b>  上傳任務(wù)隊(duì)列</b></p><p>  CUploadQueue是上傳隊(duì)列類。這個(gè)列表類中只有以CUpDownClient為元素的列表,它和其它列表類還有一個(gè)很大的不同就是它所保存的信息都不需要持久化,即

49、不需要在當(dāng)前的emule退出后還記住自己正在給誰(shuí)上傳文件,然后下次上線的時(shí)候再繼續(xù)給他們傳,這在大部分情況下是沒(méi)有意義的。上傳隊(duì)列類列表中有兩個(gè)列表,上傳列表和排隊(duì)列表。當(dāng)一個(gè)收到一個(gè)新的下載請(qǐng)求后,它會(huì)把對(duì)應(yīng)的客戶端先添加到排隊(duì)列表中,以后再根據(jù)情況,把它們不斷添加到上傳列表中。在這里,信譽(yù)機(jī)制將會(huì)對(duì)此產(chǎn)生影響。CUploadQueue的Process方法就相對(duì)簡(jiǎn)單了,那就是向上傳隊(duì)列中的所有客戶端依次發(fā)送數(shù)據(jù),而排隊(duì)的客戶端

50、是不會(huì)得到這個(gè)機(jī)會(huì)的。另外它還需要完成關(guān)于上傳方面的一些統(tǒng)計(jì)信息。另外我們還需要注意在CUploadQueue的構(gòu)造函數(shù)里面,創(chuàng)建了一個(gè)以100毫秒為間隔的定時(shí)器,這個(gè)定時(shí)器成為以上所有的Process所需要的基礎(chǔ)。我們看它的UploadTimer就可以看出這一點(diǎn)。這里面充斥了各個(gè)類的Process方法的執(zhí)行,其中包括以前我們提到的一些類,但是沒(méi)有提到它們的Process方法,因?yàn)槠溥^(guò)于簡(jiǎn)</p><p> 

51、 emule中代碼量最大的類CUpDownClient</p><p>  CUpDownClient類的作用是從邏輯上表示一個(gè)其它的客戶端的各種信息,它是emule中代碼量最大的類。我們注意到,定義它的頭文件是UpDownClient.h,但是卻沒(méi)有對(duì)應(yīng)的CUpDownClient.cpp,而它的實(shí)現(xiàn),都分散到BaseClient.cpp,DownloadClient.cpp,PeerCacheClient.c

52、pp,UploadClient.cpp和URLClient.cpp中。BaseClient.cpp中實(shí)現(xiàn)的是該類的一些基本的功能,包括基本的各種狀態(tài)信息的獲取和設(shè)置,以及按照要求處理和發(fā)送各種請(qǐng)求。在這里,邏輯實(shí)現(xiàn)和網(wǎng)絡(luò)進(jìn)行了區(qū)分,CUpDownClient類本身不從網(wǎng)絡(luò)接受或者發(fā)送消息,它只是提供各種請(qǐng)求的處理接口,以及在發(fā)送請(qǐng)求時(shí),構(gòu)造好相應(yīng)的Packet,并交給自己對(duì)應(yīng)的網(wǎng)絡(luò)套接字發(fā)出去。DownloadClient.cp

53、p中實(shí)現(xiàn)的是和下載相關(guān)的功能,它包括了各種下載請(qǐng)求的發(fā)送以及相應(yīng)的數(shù)據(jù)的接收。另外還有一個(gè)A4AF的機(jī)制,它是emule中的一個(gè)機(jī)制,因?yàn)橐粋€(gè)客戶端在同一個(gè)時(shí)間內(nèi)只能向另外一個(gè)客戶端請(qǐng)求同一個(gè)文件。這樣,對(duì)于很多個(gè)下載任</p><p>  emule常規(guī)部分小結(jié)</p><p>  emule中還有其它的很多類,它們使得emule的功能更加的強(qiáng)大和完善。有很多類在前面沒(méi)有提到,但是不代表

54、它沒(méi)有作用。而且即時(shí)是前面提到的類也只是大體的介紹,它們之間互相配合的一些細(xì)節(jié)沒(méi)有體現(xiàn)。但是這些細(xì)節(jié)應(yīng)該已經(jīng)可以通過(guò)對(duì)它們的大體的功能的了解而更加容易被把握。至于GUI的設(shè)計(jì),它也最終是要對(duì)應(yīng)到某個(gè)功能實(shí)現(xiàn)類的數(shù)據(jù)的。對(duì)于emule中的通信協(xié)議只是大體得描述了一下它的數(shù)據(jù)包的格式,但是并沒(méi)有詳細(xì)得描述它的每一個(gè)Opcode對(duì)應(yīng)的包的意義,因?yàn)槲艺J(rèn)為這是沒(méi)有必要的,在知道通信協(xié)議的格式以及處理它們的代碼所在的位置后,可以很簡(jiǎn)單的通過(guò)追

55、蹤某條消息的前因后果把整個(gè)通信協(xié)議都分析出來(lái)。這里再稍微提一下在emule中使用到的其它類及其功能。我們可以看到,如果單純只是為了能夠搜到以及下載到文件的話,有不少類是可以精簡(jiǎn)的,但是,正是由于它們的存在,使得emule的功能更加的完善。CIPFilter,IP地址過(guò)濾器,通過(guò)識(shí)別各種類型的IP地址過(guò)濾信息,它能夠把不希望連接的網(wǎng)絡(luò)地址過(guò)濾掉,emule中所有需要連接網(wǎng)絡(luò)的地方使用的都是統(tǒng)一的過(guò)濾數(shù)據(jù)。CWebServer能夠在本地

56、打開(kāi)一個(gè)Web</p><p>  eMule源代碼解析 -5</p><p>  2006-10-16 17:53</p><p>  emule中的Kademlia代碼總體描述</p><p>  當(dāng)emule中開(kāi)始使用Kademlia網(wǎng)絡(luò)后,便不再會(huì)有中心服務(wù)器失效這樣的問(wèn)題了,因?yàn)樵谶@個(gè)網(wǎng)絡(luò)中,沒(méi)有中心服務(wù)器,或者說(shuō),所有的用戶都是服

57、務(wù)器,所有的用戶也是客戶端,從而完完全全得實(shí)現(xiàn)了P2P。接下來(lái)講針對(duì)emule中的Kademlia網(wǎng)絡(luò)進(jìn)行分析,會(huì)有一節(jié)進(jìn)行原理方面的分析。另外的幾節(jié)將會(huì)根據(jù)emule中實(shí)現(xiàn)Kademlia所使用的不同的類分別進(jìn)行講述。其中:CKademlia是整個(gè)Kademlia網(wǎng)絡(luò)的主控類,可以直接開(kāi)始或者停止Kademlia網(wǎng),并且含有Process方法來(lái)處理日常事務(wù)。CPrefs負(fù)責(zé)處理自身的Kademlia相關(guān)信息,如自身的ID等。

58、CRoutingZone,CRoutingBin和CContact三個(gè)類組成了每個(gè)節(jié)點(diǎn)所了解的聯(lián)系信息以及由這些聯(lián)系信息所組成的數(shù)據(jù)結(jié)構(gòu)。CKademliaUDPListener負(fù)責(zé)處理網(wǎng)絡(luò)信息。CIndexed負(fù)責(zé)處理本地存儲(chǔ)的索引信息。CSearch,CSearchManager負(fù)責(zé)處理和搜索有關(guān)的操作,其中前者表示的是一個(gè)單一的搜索任務(wù),后者負(fù)責(zé)對(duì)所有搜索任務(wù)進(jìn)行處理。CUInt128負(fù)責(zé)處</p>

59、<p>  emule中的Kademlia的基本原理</p><p>  Kademlia是一種結(jié)構(gòu)化的覆蓋網(wǎng)絡(luò)(Structured Overlay Network),所謂的覆蓋網(wǎng)絡(luò),就是一種在物理的Internet上面再次構(gòu)建的虛擬網(wǎng)絡(luò),所有參與的節(jié)點(diǎn)都知道一部分其它節(jié)點(diǎn)的IP地址,這些節(jié)點(diǎn)稱為它的鄰居,如果需要查找什么東西,它先在本地尋找,如果找不到,就把這個(gè)查詢轉(zhuǎn)發(fā)到它的鄰居處,希望能夠有可能

60、查找到相應(yīng)的結(jié)果。覆蓋網(wǎng)絡(luò)里面分成了結(jié)構(gòu)化和非結(jié)構(gòu)化的兩種情況,它們的區(qū)別在于每個(gè)節(jié)點(diǎn)知道哪些其它節(jié)點(diǎn)的信息是否有特定的規(guī)律。在非結(jié)構(gòu)化的覆蓋網(wǎng)中,每個(gè)節(jié)點(diǎn)的鄰居狀況沒(méi)有特定的規(guī)律。因此在非結(jié)構(gòu)化網(wǎng)絡(luò)中,如果要進(jìn)行查詢,會(huì)采取一種叫做泛洪(flooding)的方法,每個(gè)節(jié)點(diǎn)如果在本地沒(méi)有查找到想要的結(jié)果,會(huì)把查找請(qǐng)求轉(zhuǎn)發(fā)到它的鄰居中,然后再通過(guò)鄰居的鄰居這種方式來(lái)進(jìn)行一步步的查找。但是這種方法如果處理不好,會(huì)造成整個(gè)網(wǎng)絡(luò)的消息負(fù)載過(guò)大。

61、已經(jīng)有不少文章對(duì)于優(yōu)化非結(jié)構(gòu)化覆蓋網(wǎng)絡(luò)中的查詢進(jìn)行了很深入的探討。對(duì)于結(jié)構(gòu)化的覆蓋網(wǎng)絡(luò),它的特點(diǎn)是每個(gè)節(jié)點(diǎn)它會(huì)選擇和哪些節(jié)點(diǎn)做鄰居是有一定的規(guī)律的,從而在進(jìn)行搜索的時(shí)候,節(jié)點(diǎn)把搜索請(qǐng)求進(jìn)行轉(zhuǎn)發(fā)的時(shí)候它能夠通過(guò)一定的規(guī)律進(jìn)行選擇</p><p>  emule中的Kademlia的基礎(chǔ)設(shè)施類</p><p>  Kademlia的主控類是CKademlia,它負(fù)責(zé)啟動(dòng)和關(guān)閉整個(gè)Kadem

62、lia網(wǎng)的相關(guān)代碼。在它的Process函數(shù)中,會(huì)處理和Kademlia網(wǎng)相關(guān)的事務(wù),例如隔一段時(shí)間檢查某個(gè)區(qū)間的節(jié)點(diǎn)數(shù)是否過(guò)少,如果是則尋找一些新的節(jié)點(diǎn)。另外經(jīng)常對(duì)自己的鄰居進(jìn)行檢查等,這些都是屬于需要進(jìn)行日常安排的工作。所有搜索任務(wù)的日常處理也需要它來(lái)調(diào)度。它還作為Kademlia網(wǎng)的代表,向emule其它部分的代碼返回Kademlia網(wǎng)的一些統(tǒng)計(jì)信息。另一個(gè)基礎(chǔ)設(shè)施類是CPrefs,它和emule普通代碼中的CPreferen

63、ces作用類似,但是CPrefs只保留和Kademlia網(wǎng)相關(guān)的,需要長(zhǎng)期保存的本地信息。具體到這個(gè)版本來(lái)說(shuō),主要就是本地的ID。還有一個(gè)很重要的基礎(chǔ)設(shè)施就是CUInt128,實(shí)現(xiàn)對(duì)128位的ID的各種處理,前面的部分已經(jīng)提到。  </p><p>  emule中的Kademlia的聯(lián)系人列表管理</p><p>  CRoutingZone,CRoutingBin和CCo

64、ntact三個(gè)類組成了聯(lián)系人列表數(shù)據(jù)結(jié)構(gòu)。它要達(dá)到我們搜索的要求,即搜索到目標(biāo)的時(shí)間要能夠接受,而且所占用的空間也要能夠接受。首先CContact類包含的是一個(gè)聯(lián)系人的信息,主要包括對(duì)方的IP地址,ID,TCP端口,UDP端口,kad版本號(hào)和其健康程度(m_byType)。其中健康程度有0-4五個(gè)等級(jí)。剛剛加入的聯(lián)系人,也就是健康狀況未知的,這個(gè)數(shù)值設(shè)置為3。系統(tǒng)會(huì)經(jīng)常通過(guò)與各個(gè)聯(lián)系人進(jìn)行聯(lián)系的方式對(duì)其進(jìn)行健康狀況檢查,經(jīng)常能夠聯(lián)系

65、上的聯(lián)系人,這個(gè)數(shù)值會(huì)慢慢減少到0。而很就沒(méi)有聯(lián)系的,這個(gè)數(shù)值會(huì)慢慢增加,如果增加到4后再過(guò)一段時(shí)間未能成功聯(lián)系上的,則將會(huì)被從聯(lián)系人列表中刪除。CRoutingBin類包含一個(gè)CContact的列表。這里要注意的是要訪問(wèn)聯(lián)系人的信息必須通過(guò)某個(gè)CRoutingBin,CRoutingZone內(nèi)部是不直接包含聯(lián)系人信息的??梢园研碌穆?lián)系人信息往一個(gè)特定的CRoutingBin中加,當(dāng)然也可以進(jìn)行聯(lián)系人查找。它也提供方法能夠?qū)ふ页鲭x某

66、個(gè)ID距離最近的聯(lián)系人,并給出這樣的一個(gè)列表。這是相當(dāng)重要的。最</p><p>  emule中的Kademlia網(wǎng)絡(luò)消息處理</p><p>  CKademliaUDPListener負(fù)責(zé)處理所有和Kademlia網(wǎng)相關(guān)的消息。前面已經(jīng)對(duì)emule的通信協(xié)議的基本情況做了一個(gè)大概的描述,我們就可以知道,CKademliaUDPListener處理的消息一定是只和Kademlia網(wǎng)相關(guān)

67、的,分揀工作已經(jīng)在emule的普通UDP客戶端處理代碼那里處理好了。具體的消息格式前面也有一些介紹,下面會(huì)就一些具體的消息分類做說(shuō)明。首先是健康檢查方面的消息,這樣的消息就是一般的ping-pong機(jī)制。對(duì)應(yīng)的消息有KADEMLIA_HELLO_REQ和KADEMLIA_HELLO_RES。當(dāng)對(duì)本地聯(lián)系人信息列表進(jìn)行檢查時(shí),會(huì)對(duì)它們發(fā)出KADEMLIA_HELLO_REQ消息,然后處理收到的KADEMLIA_HELLO_RES消息。

68、最常用的消息是節(jié)點(diǎn)搜索消息,在Kademlia網(wǎng)絡(luò)中,進(jìn)行節(jié)點(diǎn)搜索是日常應(yīng)用所需要傳輸?shù)闹饕ⅲ膶?shí)現(xiàn)方式是迭代式的搜索。這種方式就是說(shuō)當(dāng)開(kāi)始搜索某個(gè)ID時(shí),在本地聯(lián)系人信息列表中查找到距離最近的聯(lián)系人,然后向它們發(fā)出搜索請(qǐng)求,這樣通常都能夠得到一些距離更近的聯(lián)系人信息,然后再向它們發(fā)送搜索請(qǐng)求,通過(guò)不斷得進(jìn)</p><p>  emule中的Kademlia的分布式索引管理</p><

69、;p>  Kademlia網(wǎng)絡(luò)的最大的好處是把原來(lái)需要存儲(chǔ)到中心索引服務(wù)器中的信息分散存儲(chǔ)到各個(gè)客戶端當(dāng)中,如果要說(shuō)得更加準(zhǔn)確一點(diǎn),那我們就可以說(shuō)它把這些信息分散得存儲(chǔ)到各個(gè)emule客戶端的CIndexed類當(dāng)中。我們可以具體開(kāi)始看CIndexed的設(shè)計(jì),看它是如何完成這一工作的。在這之前我們要稍微詳細(xì)得說(shuō)一下emule發(fā)布到Kademlia網(wǎng)絡(luò)中的信息的各種類型。一個(gè)文件源信息是一個(gè)文件內(nèi)容的hash值和擁有這個(gè)文件的客戶

70、端的IP地址,各種端口號(hào)以及其它信息之間的對(duì)應(yīng)關(guān)系。而一個(gè)關(guān)鍵詞信息則是該關(guān)鍵詞和它對(duì)應(yīng)的文件之間的關(guān)系。在關(guān)鍵詞信息中,它對(duì)應(yīng)的文件信息要更加詳細(xì),通常包括這個(gè)文件的文件名,文件大小,文件內(nèi)容的hash值,如果是MP3或者其它媒體文件,還會(huì)包含包括作者,生產(chǎn)時(shí)間,文件長(zhǎng)度(這個(gè)長(zhǎng)度是用時(shí)間來(lái)衡量的媒體文件的播放長(zhǎng)度),流派等等tag信息。其中文件內(nèi)容的hash值用來(lái)區(qū)分該關(guān)鍵詞對(duì)應(yīng)的不同文件。CIndexed中利用了一系列的Map

71、來(lái)存儲(chǔ)這些對(duì)應(yīng)信息,CMap是MFC中實(shí)現(xiàn)標(biāo)準(zhǔn)STL中的map的模板類,CIndexed中包含了四個(gè)這樣的類,分別用來(lái)存儲(chǔ)文件源信息,關(guān)</p><p>  emule中的Kademlia搜索任務(wù)管理</p><p>  CSearch和CSearchManager是完成具體搜索任務(wù)的。CSearch對(duì)應(yīng)的是一個(gè)具體的搜索任務(wù),它包括了一個(gè)搜索任務(wù)從發(fā)起到結(jié)束的全部過(guò)程,要注意的是搜索任務(wù)

72、并不只是指搜索文件源或者關(guān)鍵詞的任務(wù),一次發(fā)布任務(wù)它也需要?jiǎng)?chuàng)建一個(gè)CSearch對(duì)象,并且讓它開(kāi)始執(zhí)行。CSearchManager則掌握所有的搜索任務(wù),它包含了一個(gè)包含所有CSearch指針對(duì)象的CMap,使用CMap的原因是因?yàn)樗械腃Search都一定對(duì)應(yīng)一個(gè)ID,那個(gè)ID就是該CSearch所對(duì)應(yīng)的目標(biāo),不管是要查找節(jié)點(diǎn),還是要搜索或者發(fā)布信息,一定都要找到和目標(biāo)ID相近的聯(lián)系人。因此CSearchManager可以使用CMap

73、來(lái)表示所有的搜索任務(wù)。我們注意到CSearch在創(chuàng)建的時(shí)候就把自己加入到CSearchManager當(dāng)中。另外CSearch在創(chuàng)建的時(shí)候需要說(shuō)明它的類型,例如是只是為了搜索節(jié)點(diǎn)還是要搜索關(guān)鍵詞信息或者文件源信息,當(dāng)然也有可能是發(fā)布文件源信息或者關(guān)鍵詞信息。我們介紹一下CSearch的幾個(gè)方法的作用就可以大概了解CSearch的工作過(guò)程。Go是它的啟動(dòng)過(guò)程,它會(huì)開(kāi)始第一次從本地的聯(lián)系人</p><p>  EM

74、ule的配制以及編譯</p><p>  經(jīng)過(guò)多次努力編譯0.47a成功,寫(xiě)下心得,主要注意的是由于依賴了四個(gè)開(kāi)源的庫(kù),所以在配置工程連接輸入路徑時(shí)一定要正確配置,還有就是所有工程全部用/MTD方式編譯,都要用相應(yīng)的DEBUG模式,因?yàn)槭菫榱藢W(xué)習(xí)和研究,所以不提供relase的配置了,需要的話可以參考上一次的編譯。原來(lái)那次Relase模式的編譯沒(méi)有辦法調(diào)試,給研究和學(xué)習(xí)帶來(lái)不便。正確的編譯方法如下:</p&

75、gt;<p>  先下載下面4個(gè)庫(kù): Crypto++ 5.2.1 http://www.eskimo.com/~weidai/cryptopp521.zip zlib123.zip http://www.zlib.net/zlib123.zip ResizableLib 1.3 http://prdownloads.sourceforge.net/resizablelib/ResizableLib_1_3.z

76、ip?download lpng128 http://download.sourceforge.net/libpng/lpng128.zip </p><p>  eMule v0.47a的源代碼: http://www.emule-project.net/home/perl/general.cgi?l=16&rm=download </p><p>  1.eMule0.4

77、7a-Sources.zip解壓到 eMule0.46b-Sources ->把下載的東東都放進(jìn)去->打開(kāi)eMule0.46b-Sources文件夾,所有的附加包都按照下述命名要求放入sources文件夾中,和srchybrid同級(jí)。所有的工程都用Multi-threaded(/MT)           

78、0;  編譯模式</p><p>  2.cryptopp521.zip解壓到 cryptopp521 ->重命名為crypto51 打開(kāi) crypto51\cryptest.dsw                  

79、 點(diǎn)生成 -> 生成解決方案 編譯模式:Debug模式</p><p>  3.zlib123.zip解壓到 zlib123 ->重命名為zlib 打開(kāi) zlib\projects\visualc6\zlib.dsw 點(diǎn)生成 -> 配置管理器 ->活動(dòng)的解決方案配置 ->LIB Debug 解決方案資源管理器 -> 右擊 "zlib" -

80、>屬性 ->配置屬性->C/C++->代碼生成->運(yùn)行時(shí)庫(kù)->多線程調(diào)試(/MTd) 點(diǎn)生成 -> 生成解決方案                   編譯模式: LIB_DEBUG模式</p><

81、;p>  4.ResizableLib_1_3.zip解壓到當(dāng)前文件夾 打開(kāi) ResizableLib\ResizableLib.dsw 點(diǎn)項(xiàng)目->屬性 ->配置屬性 ->常規(guī)->MFC的使用->在靜態(tài)庫(kù)中使用 MFC 點(diǎn)項(xiàng)目->屬性 ->配置屬性 ->常規(guī)->字符集->使用 Unicode 字符集 點(diǎn)項(xiàng)目->屬性 ->配置屬性 ->C/C++-

82、>代碼生成->運(yùn)行時(shí)庫(kù)->多線程調(diào)試(/MTd) 點(diǎn)項(xiàng)目->屬性 ->配置屬性 ->C/C++->語(yǔ)言->將 wchar_t 視為內(nèi)置類型->是(/Zc:wchar_t) 點(diǎn)生成 -> 生成解決方案 編譯模式: DEBUG Static模式</p><p>  5.lpng128.zip解壓到當(dāng)前文件夾->重命名為png 打開(kāi) png\pr

83、ojects\visualc6\libpng.sln 點(diǎn)生成 -> 配置管理器 ->活動(dòng)的解決方案配置 ->LIB Debug 解決方案資源管理器 -> 右擊 "libpng" ->屬性 ->配置屬性->C/C++->代碼生成->運(yùn)行時(shí)庫(kù)->多線程調(diào)試(/MTd) 點(diǎn)生成 -> 生成解決方案 編譯模式: LIB_DEBUG模式</p>

84、;<p>  6.打開(kāi) id3lib\libprj\id3lib.sln 點(diǎn)生成 -> 生成解決方案 編譯模式:Debug模式</p><p>  7.打開(kāi) srchybrid\lang\lang.sln 點(diǎn)生成 -> 生成解決方案 /*可能會(huì)出現(xiàn)‘ 非法操作‘ 不管它*/ </p><p>  8.打開(kāi) srchybrid\CxImage\cximage.

85、sln 點(diǎn)生成 -> 生成解決方案 編譯模式:Debug模式9.打開(kāi) srchybrid\emule_vc71.sln 點(diǎn)項(xiàng)目->屬性 ->配置屬性 ->鏈接器 ->輸入->附加依賴項(xiàng)->version.lib winmm.lib ws2_32.lib gdiplus.lib ADSIId.lib crypt32.lib ..\zlib\projects\visualc6\Win32_

86、LIB_Debug\zlibd.lib ..\crypto51\debug\cryptlib.lib ..\id3lib\libprj\id3libD.lib .\CxImage\debug\cximage.lib ..\png\projects\visualc71\Win32_LIB_Debug\pngd.lib ..\ResizableLib\Debug_Static\ResizableLib.lib</p><

87、p> ?。ㄗ⒁馍厦娴穆窂胶妥约壕幾g出來(lái)的庫(kù)名可能會(huì)有一部分不相符,要注意哦!自己好好核對(duì),把附加庫(kù)的路徑和名字都寫(xiě)對(duì)了?。┚幾g模式:Debug模式</p><p>  編譯環(huán)境:XP pro SP2, VS.net 2003  </p><p>  eMule源代碼學(xué)習(xí)心得 </p><p>  1, eMule源代碼學(xué)習(xí)心得(1):eM

88、ule代碼的總體風(fēng)格和其它相關(guān)工程</p><p>  eMule的官方首頁(yè)上寫(xiě)著:2002年05月13日 一個(gè)叫做 Merkur 的人,他不滿意原始eDonkey2000客戶端并且堅(jiān)信他能夠做的更好,所以他開(kāi)始制作。他聚集了其它開(kāi)發(fā)人員在他的周圍,并且eMule工程就此誕生。</p><p>  eMule是一個(gè)典型的MFC程序,它的圖形界面等,已經(jīng)和MFC緊緊融合到了一起。因此通常情況

89、下它只能在windows平臺(tái)下運(yùn)行。有一些其它的工程,如aMule等,把它進(jìn)行了移植,因此跨平臺(tái)的功能要強(qiáng)些。</p><p>  其實(shí)還有另外一個(gè)叫做xMule的工程,不過(guò)現(xiàn)在已經(jīng)人氣快不行了。在aMule的主頁(yè)上可以看到eMule移植到linux平臺(tái)下的一些歷史,最早是有個(gè)叫做lMule的工程,他使用wxwidgets來(lái)進(jìn)行eMule的跨平臺(tái)的移植,這個(gè)工程2003年就不再更新了,后來(lái)轉(zhuǎn)變成為xMule工程,

90、它一度是linux平臺(tái)下eMule的事實(shí)上的替代品。但是他們的程序員之間由于理念不同,發(fā)生了內(nèi)訌,導(dǎo)致aMule分裂出來(lái),他們后來(lái)矛盾嚴(yán)重的時(shí)候曾經(jīng)一度從理念問(wèn)題上升到互相對(duì)對(duì)方進(jìn)行人身攻擊,并且曾經(jīng)對(duì)對(duì)方的網(wǎng)站發(fā)動(dòng)過(guò)DDos。后來(lái)aMule和xMule就是兩個(gè)完全不同的工程,xMule現(xiàn)在只有HopeSeekr一個(gè)人在維護(hù),基本上也沒(méi)有什么更新了。這一點(diǎn)不僅讓人感慨。今年寒假的時(shí)候我曾經(jīng)和HopeSeekr進(jìn)行過(guò)一些交流,感覺(jué)他非常自

91、信,經(jīng)常拿著aMule的一部分代碼來(lái)給我看,說(shuō)你看看他們的代碼這么這么寫(xiě),這簡(jiǎn)直就是一陀xx嘛,這種代碼在某些情況下肯定會(huì)Crash掉嘛,相反,你看看我們xMule的代碼,這里是這樣這樣,肯定就不會(huì)有這種問(wèn)題了。</p><p>  eMule從0.42版開(kāi)始支持Kad技術(shù),這是一個(gè)非常重要的里程碑。Kad是一種DHT的協(xié)議,它可以使節(jié)點(diǎn)之間互相保留一些其它節(jié)點(diǎn)的聯(lián)系信息,并且利用這樣一個(gè)“關(guān)系網(wǎng)”尋找到整個(gè)網(wǎng)絡(luò)

92、中的任何一個(gè)節(jié)點(diǎn)以及上面的資源,整個(gè)過(guò)程不需要任何中心服務(wù)器。因此向當(dāng)年搞napster那樣直接端掉中心服務(wù)器就搞跨napster網(wǎng)絡(luò)一樣來(lái)對(duì)付eMule的Kad網(wǎng)就毫無(wú)作用了。0.42版是2004年2月27日放出的,比eDonkey2000的OverNet晚了將近一年,但是它的Kad網(wǎng)絡(luò)的規(guī)模卻在迅速擴(kuò)大。Overnet和eMule中的Kad使用的都是Kademlia結(jié)構(gòu),但是具體的消息報(bào)文的格式有區(qū)別,因此兩個(gè)DHT網(wǎng)絡(luò)并不能互相兼

93、容。OverNet直到現(xiàn)在,用戶也仍然維持在十萬(wàn)左右,這是比較近的一篇文章寫(xiě)的。但是eMule的Kad網(wǎng)的規(guī)模有多大,目前卻沒(méi)有一個(gè)很準(zhǔn)確的說(shuō)法。由此也可以看出開(kāi)源軟件的力量。目前aMule的Kad網(wǎng)和eMule的Kad網(wǎng)是兼容的,xMule中還沒(méi)有Kad的支持。Kad協(xié)議的原始paper可以在我們實(shí)驗(yàn)室的機(jī)器上下到:</p><p>  http://bigpc.net.pku.edu.cn:8080/pape

94、r/new/by%20conference/IPTPS/IPTPS02/Kademlia%20A%20Peer-to-Peer%20Information%20System%20Based%20on%20the%20XOR%20Metric%28IPTPS02%29.pdf</p><p>  2. eMule源代碼學(xué)習(xí)心得(2):從emule.cpp開(kāi)始,順便談如何編譯emule</p><

95、p>  先說(shuō)一聲抱歉,因?yàn)榍皟商靹偦氐郊抑?,休息了一下,所以這兩天沒(méi)有更新。今天繼續(xù)昨天的話題。</p><p>  eMule的代碼結(jié)構(gòu)非常合理。雖然代碼量比較大,但是各個(gè)功能模塊之間的劃分都很合理。從它的工程文件里面就可以看出這一點(diǎn)。eMule把表示功能的代碼文件和表示界面的代碼文件分開(kāi)了,Source Files和Header Files是實(shí)現(xiàn)功能的代碼的源文件和頭文件,而Interface Sour

96、ce和Interface Header是實(shí)現(xiàn)圖形界面的源文件和頭文件。由于eMule的代碼量太大,本系列將跳過(guò)圖形界面的實(shí)現(xiàn),著重分析eMule的功能實(shí)現(xiàn)部分的代碼,而且功能實(shí)現(xiàn)方面也主要挑主要的部分分析。本節(jié)將從emule.cpp開(kāi)始分析,引出eMule中使用到的幾個(gè)主要的功能實(shí)現(xiàn)的類,并大體描述它們的作用。最后介紹一下如何在VS2003下編譯eMule。emule中還有不少模塊實(shí)現(xiàn)的功能挺有用,我說(shuō)的是在其它的程序里很有用,可以考慮

97、在其它程序中進(jìn)行復(fù)用。</p><p>  emule.cpp為類CemuleApp的實(shí)現(xiàn)。因此在運(yùn)行時(shí),首先會(huì)運(yùn)行InitInstance進(jìn)行一些初始化的工作。從這個(gè)函數(shù)里面我們也可以第一次看出那些即將在整個(gè)程序中發(fā)揮作用的類了。</p><p>  最開(kāi)始的時(shí)候是計(jì)算出程序常用的一些目錄,如配置文件,日志文件等。接下來(lái)是ProcessCommandline,它的作用有兩方面,第一是確認(rèn)

98、該eMule的運(yùn)行方式,即命令行后面有沒(méi)有參數(shù),第二是確認(rèn)目前eMule是不是只有一個(gè)實(shí)例在運(yùn)行。在一般的情況下,雙擊eMule可執(zhí)行文件是不會(huì)帶參數(shù)的。但是通過(guò)點(diǎn)擊鏈接或者打開(kāi)關(guān)聯(lián)文件的方式打開(kāi)eMule則相當(dāng)于帶參數(shù)運(yùn)行eMule。通過(guò)在注冊(cè)表里添加一些項(xiàng)目可以讓一個(gè)程序和某種鏈接或者某個(gè)后綴的文件產(chǎn)生關(guān)聯(lián)。具體辦法可以參見(jiàn)OtherFunctions.cpp中的Ask4RegFix,BackupReg,RevertReg三個(gè)函數(shù)的

99、功能。ProcessCommandline中通過(guò)創(chuàng)建帶有名稱的互斥信號(hào)量來(lái)確認(rèn)是否有其它的eMule實(shí)例在運(yùn)行。對(duì)于一個(gè)確定的名稱,CreateMutex只能創(chuàng)建一個(gè)互斥信號(hào)量。因此通過(guò)該信號(hào)量是否創(chuàng)建成功就可以知道是否有其它eMule實(shí)例運(yùn)行。如果有的話,而且又是帶參數(shù)的那種模式,那么直接把這個(gè)參數(shù)使用Windows的消息機(jī)制發(fā)給那個(gè)窗口即可,接下來(lái)的代碼無(wú)非就是如何找到另外一個(gè)叫"eMule"的家伙以及給它發(fā)個(gè)什

100、么</p><p>  下面兩個(gè)比較重要的類是CPreferences和CStatistics。前者掌握著程序的大部分配置數(shù)據(jù),后者則進(jìn)行各種統(tǒng)計(jì)。它們的特點(diǎn)都是有很多的成員變量,而且還是靜態(tài)的,這種方式可以保證它們的唯一性,而且把這些變量統(tǒng)一到一個(gè)類管理。但是實(shí)際上并不需要了解每個(gè)變量的含義。thePrefs和theStats是這兩個(gè)類的唯一的實(shí)例。</p><p>  在處理完其它一些

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論