



下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、eMule源代碼解析 -2 2006-10-16 17:4 1分塊機(jī)制-正確傳輸資源的保證 為了加快內(nèi)容分發(fā)的速度,分塊處理是一種簡單有效的方法。emule中對(duì)每個(gè)文件都進(jìn)行了分塊處理。另外分塊還有一個(gè)好處就是如果保留了每一分塊的hash值,就能在只下載到文件的一部分時(shí)判斷出下載內(nèi)容的有效性。 emule在獲取每個(gè)共享文件的信息時(shí),就對(duì)它進(jìn)行了分塊處理,因此如果要知道emule中的分塊處理和恢復(fù)機(jī)制,看CKnownFile:CreateFromFile函數(shù)的實(shí)現(xiàn)就行了。 這個(gè)函數(shù)中牽涉到的和分塊處理以及hash計(jì)算相關(guān)的類都在SHAHashSet.cpp和SHAHashSet.h中。 下面介紹
2、其中幾個(gè)主要的類: CAICHHash類只負(fù)責(zé)一塊hash值,提供兩個(gè)CAICHHash類之間的直接賦值,比較等基本操作。CAICHHashAlgo是一個(gè)hash算法的通用的接口,其它hash算法只要實(shí)現(xiàn)這種接口都能使用,這樣,可以很方便得使用不同的hash算法來計(jì)算hash值。CAICHHashTree則是一個(gè)樹狀的hash值組織方式,它有一個(gè)左子樹和右子樹成員變量,類型是指向CAICHHashTree的指針,這是一個(gè)典型的實(shí)現(xiàn)樹狀結(jié)構(gòu)的方法。CAICHHashSet中包含了一個(gè)CAICHHashTree類型的變量,它直接向CKnownFile負(fù)責(zé),代表的是一個(gè)文件的分塊信息。 SHAHas
3、hSet.h文件的開始的注釋部分向我們解釋了它的分塊的方式。這里要用到兩個(gè)常量9728000和184320,它們分別是9500k和180k。這是emule中兩種不同粒度的分塊方式,即首先把一個(gè)很大的文件分割成若干個(gè)9500k的塊,把這些塊組織成一顆樹狀的結(jié)構(gòu),然后每一個(gè)這樣的塊又分解成若干個(gè)180k的塊(52塊,再加一個(gè)140k的塊,仍然按照樹狀的結(jié)構(gòu)組織起來。最后總的結(jié)構(gòu)還是一顆樹。 CKnownFile:CreateFromFile方法是在讀取目標(biāo)文件的內(nèi)容時(shí),逐步建立起這樣一顆樹的。CAICHHashTree:FindHash能夠根據(jù)讀取到的目標(biāo)文件的偏移量和下一塊的大小,來找出對(duì)應(yīng)的樹
4、枝節(jié)點(diǎn)(就是一個(gè)指向CAICHHashTree的指針。如果有必要的話,還會(huì)自動(dòng)創(chuàng)建這些樹枝節(jié)點(diǎn)。因此在進(jìn)行分塊操作的時(shí)候,把文件從頭到尾讀一邊,整個(gè)CAICHHashTree就建立起來了,對(duì)應(yīng)的分塊hash值也賦值好了。 最后我們還需要注意的就是CKnownFile類中的hashlist變量。就是說它還單獨(dú)保留直接以9728000字節(jié)為單位的所有分塊的MD4算法的hash值。這樣對(duì)于一個(gè)文件就有了兩套分塊驗(yàn)證的機(jī)制,能夠適應(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è)計(jì)中,為了能夠更加高效得開發(fā)網(wǎng)絡(luò)相關(guān)的代碼
5、,構(gòu)建了另外的一些類作為基礎(chǔ)設(shè)施,這些基礎(chǔ)設(shè)施類的代碼也有很高的復(fù)用價(jià)值。 首先是CAsyncSocketEx類。AsyncSocketEx.h中對(duì)這個(gè)類的特點(diǎn)已經(jīng)給出了 一定的說明。它完全兼容CAsyncSocket類,即把應(yīng)用程序中所以的CAsyncSocket換成CAsyncSocketEx,程序仍然能夠和原來的功能相同,因此在使用上更加方便。但是在這個(gè)基礎(chǔ)上,它的效率更高,主要是在消息分發(fā)機(jī)制上,即它處理和SOCKET相關(guān)的消息的效率要比原始的MFC的CAsyncSocket類更高。 另外,CAsyncSocketEx類支持通過實(shí)現(xiàn)CAsyncSocketExLayer類的方式,將一個(gè)
6、SOCKET分成若干個(gè)層,從而可以很方便得實(shí)現(xiàn)許多網(wǎng)絡(luò)功能,如設(shè)置代理,或者是使用SSL進(jìn)行加密等。 另外還有ThrottledSocket.h中定義的ThrottledControlSocket類和ThrottledFileSocket類,這兩個(gè)類只定義了兩個(gè)接口。任何其它的網(wǎng)絡(luò)套接字類如果想實(shí)現(xiàn)限速的功能,只需要在其默認(rèn)的發(fā)送函數(shù)(如Send或Sendto中不發(fā)送數(shù)據(jù)而是把數(shù)據(jù)緩存起來,然后在實(shí)現(xiàn)ThrottledControlSocket或者ThrottledFileSocket接口中的SendFileAndControlData或SendControlData方法時(shí)才真正把數(shù)據(jù)發(fā)送出去
7、,這樣就能實(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類,且在該類被創(chuàng)建的時(shí)候,就新創(chuàng)建一個(gè)線程開始單獨(dú)運(yùn)行。在該類被析構(gòu)時(shí)也會(huì)自動(dòng)停止相應(yīng)的線程。這個(gè)線程的目標(biāo)函數(shù)就是RunProc,然后為了避免在RunProc函數(shù)不
8、能使用this指針的情況,它使用了RunInternal來實(shí)際完成工作線程的工作。在emule中,還有另外一個(gè)類LastCommonRouteFinder有類似的結(jié)構(gòu)。 UploadBandwidthThrottler中保存了若干的套接字(Socket隊(duì)列,這些隊(duì)列的處理方式略有不同。在標(biāo)準(zhǔn)隊(duì)列(m_StandardOrder_list里面排隊(duì)的都是實(shí)現(xiàn)了ThrottledFileSocket接口的類,通常這些類能夠傳輸文件內(nèi)容也可以傳輸控制信息。 而其它四個(gè)隊(duì)列都是實(shí)現(xiàn)ThrottledControlSocket接口的類的隊(duì)列,在這些隊(duì)列中的類主要以傳輸控制信息為主。 這四個(gè)隊(duì)列為臨時(shí)高優(yōu)先
9、級(jí),臨時(shí)普通優(yōu)先級(jí),正式高優(yōu)先級(jí),正式普通優(yōu)先級(jí)。和把套件字直接添加到普通隊(duì)列(AddToStandardList不同, QueueForSendingControlPacket把要添加到隊(duì)列的套接字全部添加到兩個(gè)臨時(shí)隊(duì)列。根據(jù)它們的優(yōu)先級(jí)添加到普通的臨時(shí)隊(duì)列。在RunInternal的大循環(huán)中,臨時(shí)隊(duì)列中的項(xiàng)目先被移到普通隊(duì)列中,然后再進(jìn)行處理。 UploadBandwidthThrottler使用了兩個(gè)臨界區(qū),兩個(gè)事件。pauseEvent是用來暫停整個(gè)大循環(huán)的動(dòng)作的。而threadEndedEvent是標(biāo)志整個(gè)線程停止的事件。sendLocker是大循環(huán)中使用的主要的臨界區(qū),而tempQ
10、ueueLocker是為兩個(gè)臨時(shí) 隊(duì)列額外添加的鎖,這樣可以一邊發(fā)送已有隊(duì)列中的套界字要發(fā)送的數(shù)據(jù),一邊把新的套接字加到隊(duì)列中。 UploadBandwidthThrottler的RunInternal中的大循環(huán)是該工作線程的日常操作。這個(gè)大循環(huán)中做了以下事情,計(jì)算本次配額,即本次循環(huán)中能夠發(fā)送多少字節(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只使用一次就離開隊(duì)列。而標(biāo)準(zhǔn)隊(duì)列中的套接字不會(huì)這樣。在一輪循環(huán)結(jié)束
11、后,如果還有沒有用完的發(fā)送數(shù)據(jù)的配額,則會(huì)有部分配額保存到下一輪。 網(wǎng)絡(luò)基礎(chǔ)設(shè)施-emule套接字CEMSocket CEMSocket是CAsyncSocketEx和ThrottledFileSocket的子類,它把若干功能整合到了一起,因此可以作為emule使用起來比較方便的套接字。例如它可以很方便得指定代理,把CAsyncSocketEx中的創(chuàng)建一個(gè)新的代理層并且添加到列表中的功能對(duì)外屏蔽了。另外它可以分出狀態(tài),如當(dāng)前是否在發(fā)送控制信息等。 CEMSocket中我們需要仔細(xì)考察的是它的SendControlData和SendFileAndControlData方法。如前所述,這些方法是用
12、來和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。這里就有了另外一個(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的SendControlData和SendFileAndControlData方法其實(shí)都是調(diào)用自己的另一個(gè)重載的Send方法。而且我們也已經(jīng)知道這個(gè)方法是在UploadBandwidthThrottler的工作線程中的大循環(huán)中被調(diào)用的,而這個(gè)Send方法的內(nèi)容本身也是一個(gè)大循環(huán),但是意義很明了,就是在不超過自己本次發(fā)送的配額的情況下,把自己的包隊(duì)列中的包取出來,并且發(fā)出去。同樣,這里也用到了一個(gè)臨界區(qū),它是為了保
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 貨幣挖礦合同范本
- 企業(yè)正規(guī)合同范本
- 別墅購銷合同范本
- 信用擔(dān)保貸款合同范本
- 制作人合同范本
- 單位房屋租用合同范本
- 中介用代管合同范本
- 農(nóng)藥國際銷售合同范本
- 關(guān)于工地買賣合同范例
- 制作安裝勞務(wù)合同范本
- 人教版體育與健康四年級(jí)-《障礙跑》教學(xué)設(shè)計(jì)
- DB32-T 2860-2015散裝液體化學(xué)品槽車裝卸安全作業(yè)規(guī)范-(高清現(xiàn)行)
- 部編版四年級(jí)下冊(cè)語文教案(完整)
- T∕CIS 71001-2021 化工安全儀表系統(tǒng)安全要求規(guī)格書編制導(dǎo)則
- 福利院裝修改造工程施工組織設(shè)計(jì)(225頁)
- 部編版六年級(jí)下冊(cè)語文課后詞語表(拼音)
- 環(huán)境空氣中臭氧的測(cè)定
- 第七章 化學(xué)物質(zhì)與酶的相互作用
- 機(jī)械畢業(yè)設(shè)計(jì)論文鋼筋自動(dòng)折彎機(jī)的結(jié)構(gòu)設(shè)計(jì)全套圖紙
- 總體施工進(jìn)度計(jì)劃橫道圖
- 教科版四年級(jí)科學(xué)下冊(cè)教學(xué)計(jì)劃及進(jìn)度表(兩篇)
評(píng)論
0/150
提交評(píng)論