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

下載本文檔

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

文檔簡介

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

56、打開一個Web</p><p>  eMule源代碼解析 -5</p><p>  2006-10-16 17:53</p><p>  emule中的Kademlia代碼總體描述</p><p>  當emule中開始使用Kademlia網(wǎng)絡(luò)后,便不再會有中心服務(wù)器失效這樣的問題了,因為在這個網(wǎng)絡(luò)中,沒有中心服務(wù)器,或者說,所有的用戶都是服

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

58、CRoutingZone,CRoutingBin和CContact三個類組成了每個節(jié)點所了解的聯(lián)系信息以及由這些聯(lián)系信息所組成的數(shù)據(jù)結(jié)構(gòu)。CKademliaUDPListener負責處理網(wǎng)絡(luò)信息。CIndexed負責處理本地存儲的索引信息。CSearch,CSearchManager負責處理和搜索有關(guān)的操作,其中前者表示的是一個單一的搜索任務(wù),后者負責對所有搜索任務(wù)進行處理。CUInt128負責處</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é)點都知道一部分其它節(jié)點的IP地址,這些節(jié)點稱為它的鄰居,如果需要查找什么東西,它先在本地尋找,如果找不到,就把這個查詢轉(zhuǎn)發(fā)到它的鄰居處,希望能夠有可能

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

75、gt;<p>  先下載下面4個庫: 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 ->把下載的東東都放進去->打開eMule0.46b-Sources文件夾,所有的附加包都按照下述命名要求放入sources文件夾中,和srchybrid同級。所有的工程都用Multi-threaded(/MT)           

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

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

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

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

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

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

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

85、sln 點生成 -> 生成解決方案 編譯模式:Debug模式9.打開 srchybrid\emule_vc71.sln 點項目->屬性 ->配置屬性 ->鏈接器 ->輸入->附加依賴項->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模式: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代碼的總體風格和其它相關(guān)工程</p><p>  eMule的官方首頁上寫著:2002年05月13日 一個叫做 Merkur 的人,他不滿意原始eDonkey2000客戶端并且堅信他能夠做的更好,所以他開始制作。他聚集了其它開發(fā)人員在他的周圍,并且eMule工程就此誕生。</p><p>  eMule是一個典型的MFC程序,它的圖形界面等,已經(jīng)和MFC緊緊融合到了一起。因此通常情況

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

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

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

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

93、容。OverNet直到現(xiàn)在,用戶也仍然維持在十萬左右,這是比較近的一篇文章寫的。但是eMule的Kad網(wǎng)的規(guī)模有多大,目前卻沒有一個很準確的說法。由此也可以看出開源軟件的力量。目前aMule的Kad網(wǎng)和eMule的Kad網(wǎng)是兼容的,xMule中還沒有Kad的支持。Kad協(xié)議的原始paper可以在我們實驗室的機器上下到:</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開始,順便談如何編譯emule</p><

95、p>  先說一聲抱歉,因為前兩天剛回到家中,休息了一下,所以這兩天沒有更新。今天繼續(xù)昨天的話題。</p><p>  eMule的代碼結(jié)構(gòu)非常合理。雖然代碼量比較大,但是各個功能模塊之間的劃分都很合理。從它的工程文件里面就可以看出這一點。eMule把表示功能的代碼文件和表示界面的代碼文件分開了,Source Files和Header Files是實現(xiàn)功能的代碼的源文件和頭文件,而Interface Sour

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

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

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

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

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

溫馨提示

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

評論

0/150

提交評論