P2P SDK開(kāi)發(fā)包與無(wú)關(guān)性協(xié)議傳輸.doc_第1頁(yè)
P2P SDK開(kāi)發(fā)包與無(wú)關(guān)性協(xié)議傳輸.doc_第2頁(yè)
P2P SDK開(kāi)發(fā)包與無(wú)關(guān)性協(xié)議傳輸.doc_第3頁(yè)
P2P SDK開(kāi)發(fā)包與無(wú)關(guān)性協(xié)議傳輸.doc_第4頁(yè)
P2P SDK開(kāi)發(fā)包與無(wú)關(guān)性協(xié)議傳輸.doc_第5頁(yè)
已閱讀5頁(yè),還剩62頁(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)介

P2P SDK開(kāi)發(fā)包與無(wú)關(guān)性協(xié)議傳輸目錄:一綜述二PPQ.DLL是一個(gè)P2P SDK開(kāi)發(fā)包三PPQ.DLL的特點(diǎn)四PPQ.DLL的工作方式五創(chuàng)建PBaseAct派生類(lèi)六在開(kāi)始一個(gè)任務(wù)之前的準(zhǔn)備工作七從URL下載一個(gè)文件八建立一個(gè)語(yǔ)音聊天九從另一個(gè)好友處下載一個(gè)文件十PPQ.DLL的無(wú)關(guān)性協(xié)義傳輸一綜述 PPQ.DLL通過(guò)對(duì)象和插件的封裝來(lái)實(shí)現(xiàn)無(wú)關(guān)性協(xié)義傳輸,允許開(kāi)發(fā)者在不必知道傳輸協(xié)議的前提下,就可以進(jìn)行插件的開(kāi)發(fā),加快開(kāi)發(fā)過(guò)程,減少錯(cuò)誤的產(chǎn)生,提供了一種用TCP來(lái)實(shí)現(xiàn)事務(wù)處理的策略,在最后提出了一種比HTTP、XML和SOAP等更加靈活的包含執(zhí)行方法的,以傳送對(duì)象的方式實(shí)現(xiàn)的無(wú)關(guān)性協(xié)義傳輸。 二PPQ.DLL是一個(gè)P2P SDK開(kāi)發(fā)包PPQ.DLL是一個(gè)P2P的SDK開(kāi)發(fā)包,它使用對(duì)象的傳遞來(lái)實(shí)現(xiàn)無(wú)關(guān)性協(xié)議傳輸,這種對(duì)象并不是MFC或JAVA的序列化對(duì)象,PPQ.DLL的序列化對(duì)象,使開(kāi)發(fā)者可以在互相不知道傳送協(xié)議的情況下,互傳消息,并且可以根據(jù)開(kāi)發(fā)者的定義,在不同的編程語(yǔ)言環(huán)境中互傳對(duì)象。它將TCP的流式數(shù)據(jù)轉(zhuǎn)變成一個(gè)個(gè)事務(wù)來(lái)對(duì)待,每一個(gè)事務(wù)表明你希望通過(guò)P2P來(lái)實(shí)現(xiàn)的功能,事務(wù)的處理過(guò)程可以使用DLL、OCX或COM等任何一種形式封裝起來(lái),這些被封裝的事務(wù)可以由其它開(kāi)發(fā)者直接在自己的開(kāi)發(fā)程序中引用,而不需要再為處理相同的事務(wù)去開(kāi)發(fā)一套程序。 PPQ.DLL采用插件的形式來(lái)引用已定義好的事務(wù)處理程序,不但可以在開(kāi)發(fā)程序時(shí)增加一個(gè)插件,而且允許程序在運(yùn)行時(shí)動(dòng)態(tài)增加或取消一個(gè)插件,使開(kāi)發(fā)出來(lái)的程序,具備動(dòng)態(tài)擴(kuò)展功能,而不必每增加一個(gè)功能都重新發(fā)布一次程序,并且這種插件地增加和取消可以完全由用戶自己來(lái)決定。PPQ.DLL封裝了數(shù)據(jù)傳輸時(shí)的編碼方式,使開(kāi)發(fā)者不用擔(dān)心開(kāi)發(fā)程序與未來(lái)P2P國(guó)際標(biāo)準(zhǔn)之間的接軌,對(duì)于新的標(biāo)準(zhǔn)的適應(yīng),只需要簡(jiǎn)單的修改一下底層的解碼器,所有原先的開(kāi)發(fā)程序就可以自動(dòng)地適應(yīng)新的國(guó)際標(biāo)準(zhǔn)。PPQ.DLL實(shí)際上提供了一種新的以對(duì)象方式實(shí)現(xiàn)的無(wú)關(guān)性協(xié)議傳輸,它類(lèi)似于XML、HTTP、SOAP等協(xié)義,但有其獨(dú)特的特點(diǎn),關(guān)于這種新的無(wú)關(guān)性協(xié)議傳輸?shù)目尚行詫⒃诤竺嬲撌觥?PPQ.DLL為P2P的應(yīng)用帶來(lái)了一個(gè)新的起點(diǎn)?,F(xiàn)在的P2P的應(yīng)用都是傳遞一種字符串來(lái)作為命令,它只能傳遞規(guī)則,而無(wú)法傳遞規(guī)則所表示的方法,并且這種規(guī)則到目前為止并沒(méi)有一個(gè)統(tǒng)一的標(biāo)準(zhǔn),如何建立標(biāo)準(zhǔn)與什么時(shí)候能夠建立標(biāo)準(zhǔn)都是一個(gè)期待的問(wèn)題。在等待標(biāo)準(zhǔn)公布時(shí),每一家大的公司都在努力制定自己的協(xié)義與標(biāo)準(zhǔn),都希望將來(lái)的標(biāo)準(zhǔn)能夠與自己的相同,在標(biāo)準(zhǔn)公布以后,所有的與標(biāo)準(zhǔn)不同的程序,如果想適應(yīng)標(biāo)準(zhǔn),都必需去修改原程序,這個(gè)改動(dòng)是很龐大的,而PPQ.DLL正是解決了這個(gè)問(wèn)題。PPQ.DLL的傳輸沒(méi)有任何的協(xié)議,任何一個(gè)開(kāi)發(fā)者都可以制定自己的協(xié)議標(biāo)準(zhǔn)去完成一個(gè)任務(wù),而不需要去關(guān)心其它的應(yīng)用程序。對(duì)于想通過(guò)P2P來(lái)實(shí)現(xiàn)的功能,只需要加入一個(gè)已經(jīng)定義好的類(lèi)就可以啦,如果想在其它開(kāi)發(fā)者開(kāi)發(fā)的事務(wù)處理程序基礎(chǔ)之上去增加一些功能,甚至可以從其他開(kāi)發(fā)者已經(jīng)定義好的類(lèi)中派生出新的本地類(lèi)來(lái)實(shí)現(xiàn)自己的獨(dú)特功能,而發(fā)送指令對(duì)象的雙方卻都可以正確地解析,并且可以在雙方的處理過(guò)程中,都引入自己獨(dú)特的本地處理方式。PPQ.DLL是一種真正地?zé)o協(xié)義傳輸方式,它的引入可以使P2P在一些關(guān)鍵性領(lǐng)域中得到真正地應(yīng)用,它的這種插件式自由組合方式,也使程序地開(kāi)發(fā)得到了最大化的復(fù)用,能夠更好地加快程序開(kāi)發(fā)速度,使每一次的開(kāi)發(fā)都不必再?gòu)钠鹋芫€上開(kāi)始。利用PPQ.DLL的對(duì)象傳遞方式,PPQ.DLL將P2P實(shí)現(xiàn)的基本功能都封裝在了DLL中,開(kāi)發(fā)者可以直接把它作為一個(gè)開(kāi)發(fā)包來(lái)使用,其他開(kāi)發(fā)者利用PPQ.DLL的對(duì)象傳遞方式開(kāi)發(fā)出的插件,也可以直接無(wú)縫地加入開(kāi)發(fā)包中,使開(kāi)發(fā)P2P產(chǎn)品變得輕松自如。PPQ.DLL也提出了防止目前P2P上盜版、黃色信息、無(wú)用的垃圾信息大量泛濫的一種方法,讓P2P的使用更加規(guī)范,使個(gè)人用戶的行為更加具有針對(duì)性和目的性。從開(kāi)發(fā)JAVA版的P2P程序開(kāi)始,我就始終認(rèn)為P2P應(yīng)該對(duì)下載的文件設(shè)定一種權(quán)限,用戶通過(guò)權(quán)限可以控制自己所提供的文件可以被哪一些人下載,這種想法也影響到了我開(kāi)發(fā)C+版的PPQ.DLL。國(guó)內(nèi)目前開(kāi)發(fā)的P2P程序中對(duì)下載文件都沒(méi)有任何的限制,其直接導(dǎo)制的后果就是大量的黃色信息呈輔射狀傳播,一個(gè)下載了黃色信息的用戶無(wú)形之中成為了一個(gè)傳播黃色信息的新的源,形成了非常壞的一個(gè)惡性循環(huán),最終導(dǎo)制目前國(guó)內(nèi)所有P2P網(wǎng)站全部暫停。PPQ.DLL對(duì)用戶的所有傳送文件采用數(shù)字標(biāo)識(shí)來(lái)傳遞,這種數(shù)字標(biāo)識(shí)可以和一些描述性的詞匯一起被傳送給其它用戶,用戶想下載時(shí),也是傳遞數(shù)字標(biāo)識(shí),而并不是直接傳遞想下載的文件名,傳送方在接收到數(shù)字標(biāo)識(shí)后通過(guò)程序去查找到該數(shù)字標(biāo)識(shí)所對(duì)應(yīng)的正確的本地文件名,在這個(gè)過(guò)程中,傳送方可以檢驗(yàn)請(qǐng)求傳送的用戶是否有權(quán)限下載該文件,如果有,則開(kāi)始傳遞文件,否則會(huì)駁回該用戶的請(qǐng)求。數(shù)字標(biāo)識(shí)的引入為安全性和擴(kuò)展性帶來(lái)了很多的好處:1用戶不必再設(shè)定某一個(gè)共享目錄,文件可以散布在本地機(jī)器的任何一個(gè)目錄下,而不用擔(dān)心安全性。2避免了垃圾文件的出現(xiàn),設(shè)定共享目錄時(shí),用戶常常將一大堆文件拷貝到目錄下,結(jié)果檢索出來(lái)的經(jīng)常是一大堆垃圾。3可以為任何一個(gè)文件加入權(quán)限設(shè)定,使用戶可以靈活得控制每一個(gè)文件的一個(gè)或一組下載方。4每一下載方只能看到自己可以下載的內(nèi)容,不在權(quán)限內(nèi)的下載內(nèi)容根本就看不到。5為將來(lái)的應(yīng)用增加了可擴(kuò)展性,從數(shù)字標(biāo)識(shí)到正確的本地文件的轉(zhuǎn)換過(guò)程,提供了一種方便地?cái)U(kuò)展手段,以什么方式來(lái)設(shè)定權(quán)限、如何校驗(yàn)權(quán)限、是否使用權(quán)限、以及對(duì)不同文件采取不同加密手段等都可以在這個(gè)轉(zhuǎn)換過(guò)程中根據(jù)具體情況來(lái)定義。 通過(guò)以上方法,只能防止文件的泛濫傳播,還不能有效地控制黃色信息。從用戶端來(lái)控制黃色信息是很困難的,因?yàn)閷?xiě)的任何一個(gè)過(guò)濾代碼都很容易就會(huì)被破解,從而根本起不到過(guò)濾黃色信息的目的,所以最終還是應(yīng)該從服務(wù)器來(lái)控制。PPQ.DLL的想法是將用戶提供的公共信息源采用分布式數(shù)據(jù)庫(kù)的方式保存,由專門(mén)的服務(wù)器提供一個(gè)強(qiáng)大的搜索引擎,用戶通過(guò)這個(gè)搜索引擎來(lái)檢索公共信息,在這個(gè)搜索引擎中設(shè)置過(guò)濾器,濾除黃色信息,這是避免黃色信息泛濫傳播的一個(gè)有效方法。(用戶在幾個(gè)人的小范圍內(nèi)進(jìn)行的傳播,應(yīng)該不在考慮范圍之內(nèi),而且也根本就不可能完全地控制住。)PPQ.DLL在服務(wù)器開(kāi)發(fā)方面,提出了一種“全球服務(wù)器統(tǒng)一資源分配”策略,這種方式,對(duì)服務(wù)器的負(fù)擔(dān)非常輕,可以由任意多個(gè)服務(wù)器提供商去獨(dú)立地創(chuàng)建自己的用戶群,建立自己的用戶檔案庫(kù),彼此間不需要頻繁交換信息,也不需要彼此共享用戶資源,更用不著建立中心數(shù)據(jù)庫(kù),但是在任何一臺(tái)服務(wù)器上登錄的用戶彼此間卻可以互相通訊,可以不通過(guò)服務(wù)器而建立連接。 三PPQ.DLL的特點(diǎn)1在P2P標(biāo)準(zhǔn)尚未統(tǒng)一的情況下,開(kāi)發(fā)者都在獨(dú)立的制定自己的傳送協(xié)議,使開(kāi)發(fā)出來(lái)的程序彼此無(wú)法互相通訊,而且采用不同編程語(yǔ)言開(kāi)發(fā)出的產(chǎn)品,在互相通信時(shí)也會(huì)存在問(wèn)題,PPQ.DLL正是為解決這個(gè)問(wèn)題而開(kāi)發(fā)的。PPQ.DLL是建立在任何一種標(biāo)準(zhǔn)協(xié)議之上的一種公共接口,它不但能簡(jiǎn)化開(kāi)發(fā)過(guò)程,而且標(biāo)準(zhǔn)化了傳送和接收的過(guò)程,使開(kāi)發(fā)者可以在各自制定協(xié)議的前提下,仍然能夠?qū)崿F(xiàn)互相通訊,并且可以在采用不同的編程語(yǔ)言開(kāi)發(fā)的產(chǎn)品之間互相傳遞指令對(duì)象。2PPQ.DLL封裝了采用TCP進(jìn)行文件傳送與接收的全過(guò)程。只需要給出連接方的IP地址、監(jiān)聽(tīng)端口號(hào)和想傳送(或下載)的文件的數(shù)字標(biāo)識(shí)號(hào),PPQ.DLL會(huì)自動(dòng)地以多線程、斷點(diǎn)續(xù)傳的方式實(shí)現(xiàn)文件的傳送與接收過(guò)程。3PPQ.DLL封裝了以HTTP方式從URL地址下載文件的全過(guò)程。只需要給出想下載的URL地址,PPQ.DLL會(huì)自動(dòng)地根據(jù)服務(wù)器端是否支持?jǐn)帱c(diǎn)續(xù)傳,來(lái)決定采用單線程還是多線程方式下載。支持重定向。4PPQ.DLL封裝了以TCP方式進(jìn)行語(yǔ)音聊天的全過(guò)程,只需簡(jiǎn)單地調(diào)用幾個(gè)靜態(tài)函數(shù),就可以輕易地啟動(dòng)、暫停、關(guān)閉聲音捕捉(錄音)和聲音回放(放音),并初步實(shí)現(xiàn)了靜音過(guò)濾。5PPQ.DLL封裝了進(jìn)行數(shù)據(jù)傳輸?shù)木幋a方式和傳送的具體過(guò)程,將數(shù)據(jù)的傳送和接收轉(zhuǎn)變成對(duì)象的傳送和接收,使處理過(guò)程標(biāo)準(zhǔn)化。使用PPQ.DLL來(lái)開(kāi)發(fā)程序,不用直接和字符串打交道,不必再去解析從SOCKET接收到的字符串編碼,開(kāi)發(fā)者可以將想傳送的信息定義成指令對(duì)象的屬性,直接發(fā)送指令對(duì)象,PPQ.DLL會(huì)自動(dòng)將指令對(duì)象轉(zhuǎn)變成數(shù)據(jù)流發(fā)出。SOCKET所接收到的數(shù)據(jù),PPQ.DLL會(huì)自動(dòng)轉(zhuǎn)變成對(duì)應(yīng)的指令對(duì)象,以WINDOWS消息或回調(diào)函數(shù)的方式通知接收方,使整個(gè)的開(kāi)發(fā)過(guò)程變得更加簡(jiǎn)單和模塊化。6PPQ.DLL的對(duì)象數(shù)據(jù)流處理并不是MFC的序列化對(duì)象,它比MFC的序列化對(duì)象更加簡(jiǎn)單、易用,允許在修改對(duì)象屬性后,重復(fù)發(fā)送對(duì)象,而且能夠在無(wú)法實(shí)別所傳送的類(lèi)對(duì)象時(shí),自動(dòng)還原成與該類(lèi)最接近的一個(gè)基類(lèi)的對(duì)象。PPQ.DLL的序列化解碼過(guò)程采用純C+編寫(xiě),可以很容易地改寫(xiě)成其它的語(yǔ)言。7PPQ.DLL的對(duì)象流的實(shí)現(xiàn)過(guò)程和方法被完全地封裝在了DLL中,對(duì)于實(shí)現(xiàn)對(duì)象流的算法的優(yōu)化,甚至是改變對(duì)象流的傳送格式,都不會(huì)對(duì)使用PPQ.DLL的開(kāi)發(fā)者造成任何影響,使開(kāi)發(fā)者可以完全放心地開(kāi)發(fā)程序,而不用擔(dān)心標(biāo)準(zhǔn)與協(xié)議的改變。經(jīng)過(guò)數(shù)次的改寫(xiě)和優(yōu)化,正式版的PPQ.DLL不但可以傳送任意大小的指令對(duì)象,并且在接收指令對(duì)象時(shí),從SOCKET中讀出的數(shù)據(jù)將直接被寫(xiě)到指令對(duì)象相應(yīng)的屬性的緩沖區(qū)中,中間不再需要經(jīng)過(guò)任何一次緩沖區(qū)的復(fù)制過(guò)程,大大地加快了速度。8如果你認(rèn)為使用PPQ.DLL開(kāi)發(fā)的不同產(chǎn)品,只不過(guò)是界面上的不同,那你就錯(cuò)啦。PPQ.DLL提供了豐富的接口和靈活的開(kāi)發(fā)方式,使你完全可以開(kāi)發(fā)出具有鮮明特點(diǎn)和獨(dú)立功能的程序。PPQ.DLL只是封裝了連接實(shí)現(xiàn)的過(guò)程和握手協(xié)議,對(duì)建立連接后,雙方傳送的信息并沒(méi)有作出任何規(guī)定和假設(shè),它只是提供了一種公共的接口。9開(kāi)發(fā)者可以根據(jù)自己的需要去創(chuàng)建新的類(lèi),來(lái)表明一種類(lèi)型的指令,這種類(lèi)型的指令完成一種特定的功能,開(kāi)發(fā)者可以將自己創(chuàng)建的指令和指令的解析程序一起打包成一個(gè)DLL,發(fā)布出來(lái),同時(shí)公布該類(lèi)的ClassID。其它的開(kāi)發(fā)者可以在自己的程序中直接引用這個(gè)DLL,來(lái)完成由其它開(kāi)發(fā)者預(yù)先定義好的功能。PPQ.DLL內(nèi)部也定義了一些派生類(lèi),這些派生類(lèi)都是完成一種特定功能的指令對(duì)象。10PPQ.DLL提供了一個(gè)鉤子函數(shù),用來(lái)返回開(kāi)發(fā)者自定義的類(lèi)的對(duì)象。如果你的自定義類(lèi)是你發(fā)布的DLL中的一個(gè)內(nèi)部類(lèi),即自定義的類(lèi)被完全地封裝在了你提供的DLL中,那么這個(gè)類(lèi)的類(lèi)名可以是任意的,不用擔(dān)心會(huì)重名。當(dāng)其他開(kāi)發(fā)者要使用你的DLL時(shí),只需要增加你提供的鉤子函數(shù)即可。但是類(lèi)的ClassID還是需要公布的,以避免與其他開(kāi)發(fā)者的ClassID重復(fù)。握手協(xié)議的傳遞和語(yǔ)音聊天的傳送與接收采用的就是指令對(duì)象的方式來(lái)進(jìn)行傳送,這些對(duì)象都被封裝在了PPQ.DLL內(nèi)部,開(kāi)發(fā)者只需要通過(guò)接口來(lái)啟動(dòng)一個(gè)或一組功能,而不需要直接去同這些對(duì)象打交道。因?yàn)檫@些類(lèi)被完全地封裝在了PPQ.DLL內(nèi)部,因此,即使你在開(kāi)發(fā)過(guò)程中定義了一個(gè)與這些對(duì)象重名的類(lèi),也不會(huì)對(duì)程序造成任何的影響。 四 PPQ.DLL的工作方式PPQ.DLL通過(guò)消息與回調(diào)函數(shù)和DLL外部進(jìn)行交互,要想正確地使用這個(gè)DLL,就需要了解PPQ.DLL中對(duì)外發(fā)布的幾個(gè)類(lèi)。PPQ.DLL中一共對(duì)外提供了5個(gè)類(lèi):PDefine、PFriend、PBaseAct、PTask和CStringEx。 PDefine類(lèi)中定義了開(kāi)發(fā)者需要使用的結(jié)構(gòu)、回調(diào)函數(shù)、常量以及PPQ.DLL定義的一些消息和靜態(tài)方法。這個(gè)類(lèi)不需要去創(chuàng)建實(shí)例,它里面的所有方法和屬性都是靜態(tài)的。這些定義對(duì)正確地了解和撐握PPQ.DLL是非常關(guān)鍵的。 PPQ的整個(gè)連接過(guò)程是建立在一種信任的基礎(chǔ)之上的。即如果A信任B,B也信任A,那么A與B之間可以互相連接,否則連接不能被建立。這種信任的關(guān)系不能夠被繼承,即如果A信任B,B信任A、C,C信任B,這并不表示A也信任C,A可以和B之間互連,B即可以和A,也可以和C之間互連,但A不可以和C這間互連。即信任只能是雙方的事情。這種信任關(guān)系的表現(xiàn)的實(shí)體,就是PFriend類(lèi)。PFriend類(lèi)中定義了被連接方的身份標(biāo)識(shí)(ID)、IP地址、監(jiān)聽(tīng)端口號(hào)等相關(guān)信息,是對(duì)被連接方的一個(gè)描述(連接與被連接都是從自己這一方來(lái)看的)。通常開(kāi)發(fā)者需要從該類(lèi)中派生出新的類(lèi),以記錄關(guān)于被連接方的更多的詳細(xì)資料。在PPQ.DLL中,被連接的一方都稱為好友,每一個(gè)好友都必需有一個(gè)PFriend對(duì)象與之對(duì)應(yīng),除了進(jìn)行HTTP連接時(shí)不需要用到PFriend對(duì)象,其它進(jìn)行的所有連接都是針對(duì)于某一個(gè)PFriend對(duì)象而進(jìn)行的。希望互相連接的雙方,彼此都必需包括有對(duì)方的PFriend對(duì)象,否則連接是無(wú)法被建立的。 PPQ.DLL認(rèn)為要傳輸?shù)臄?shù)據(jù)應(yīng)該被分為2種,一種是指令,表示完成某一種功能,另一種是數(shù)據(jù),它的實(shí)際意義由以前傳遞的指令來(lái)表明。指令和數(shù)據(jù)往往是相關(guān)連的,失去任何一方,都會(huì)失去其表示的有效意義,因此,這2種實(shí)際應(yīng)該是一個(gè)整體,而這個(gè)整體在PPQ.DLL中表現(xiàn)出的實(shí)體,就是PBaseAct類(lèi)。指令和數(shù)據(jù)被封裝在一個(gè)PBaseAct類(lèi)中,作為一個(gè)整體來(lái)傳輸,這就是指令對(duì)象。PBaseAct是所有可以轉(zhuǎn)變?yōu)閿?shù)據(jù)流進(jìn)行傳輸?shù)闹噶顚?duì)象的基類(lèi),開(kāi)發(fā)者需要自定義傳輸對(duì)象時(shí),都需要從該類(lèi)來(lái)派生出新的類(lèi)。只有該派生類(lèi)的實(shí)例才可以直接作為一個(gè)對(duì)象從SOCKET中進(jìn)行傳送與接收。 建立連接應(yīng)該是有目的性的,即建立連接應(yīng)該是為了具體完成某一項(xiàng)工作,建立多個(gè)連接的目的是為了更好、更快地協(xié)同完成這項(xiàng)工作。在PPQ.DLL里,某一項(xiàng)工作用任務(wù)來(lái)表示,而任務(wù)的表現(xiàn)實(shí)體,就是PTask類(lèi)。PTask類(lèi)描述并記錄了一個(gè)或一組具有相同連接類(lèi)型的連接,它表明了要進(jìn)行的一個(gè)任務(wù)。 CStringEx類(lèi)是針對(duì)于MFC的CString類(lèi)的一個(gè)擴(kuò)展,它的主要作用是傳遞大數(shù)據(jù)量的二進(jìn)制流緩沖,通過(guò)操作符重載,CStringEx類(lèi)可以使用+=符號(hào),直接追加一個(gè)字符串或一個(gè)int類(lèi)型的數(shù)字。通過(guò)方法,還可以追加一個(gè)中間包含0終結(jié)符的二進(jìn)制的流緩沖。你可以使用CStringEx類(lèi)在任何一個(gè)需要?jiǎng)討B(tài)改變緩沖區(qū)大小的地方,代替原來(lái)的數(shù)據(jù)緩沖區(qū),包括字符緩沖區(qū)、音頻緩沖區(qū)、視頻緩沖區(qū)等接收緩沖區(qū),使用CStringEx就和使用一個(gè)char*是一樣的,在使用過(guò)程中,你可以直接得到CStringEx的數(shù)據(jù)緩沖區(qū),將它轉(zhuǎn)換成任意類(lèi)型的緩沖區(qū)來(lái)使用。CStringEx對(duì)象用來(lái)保存指令對(duì)象中需要傳送的大型數(shù)據(jù),在構(gòu)成指令對(duì)象時(shí),如果指令對(duì)象需要發(fā)送比較長(zhǎng)的數(shù)據(jù)(建議超過(guò)1K)時(shí),都應(yīng)使用CStringEx來(lái)保存,因?yàn)樵趥魉椭噶顚?duì)象時(shí),對(duì)CStringEx對(duì)象作了優(yōu)化處理,它的傳送速度會(huì)比傳送CString類(lèi)型的對(duì)象要快得多。 五 創(chuàng)建PBaseAct派生類(lèi)PPQ.DLL沒(méi)有對(duì)外提供任何的指令對(duì)象,因此,使用DLL的第一件事情,就是創(chuàng)建自己的PBaseAct派生類(lèi)。創(chuàng)建PBaseAct派生類(lèi)其實(shí)很簡(jiǎn)單,按照以下步驟,你就可以輕松地創(chuàng)建出自己的派生類(lèi)。1在派生類(lèi)的.h文件中加入SELF_SERIALIZE()序列化宏。SELF_SERIALIZE()宏需要傳遞2個(gè)參數(shù),第一個(gè)參數(shù)是當(dāng)前派生類(lèi)的類(lèi)名,第二個(gè)參數(shù)是該派生類(lèi)的直接基類(lèi)的類(lèi)名。即如果你的派生類(lèi)名為PLoginAct,它由PChatAct類(lèi)派生,則宏調(diào)用為SELF_SERIALIZE(PLoginAct,PChatAct);2在派生類(lèi)中重載CountSerializeLength()方法。3在派生類(lèi)中重載UniteValue()方法。4在派生類(lèi)中重載InitObject()方法。5在派生類(lèi)中重載GetClassID()方法,返回自定義類(lèi)的ClassID。6實(shí)現(xiàn)GOCALLBACK鉤子函數(shù),返回自定義對(duì)象的一個(gè)實(shí)例。 關(guān)于GOCALLBACK鉤子函數(shù)的定義和實(shí)現(xiàn)方法,請(qǐng)查閱PDefine.h文件中的回調(diào)函數(shù)說(shuō)明。7實(shí)現(xiàn)GETCALLBACK回調(diào)函數(shù),對(duì)自定義對(duì)象進(jìn)行處理。 或者定義一個(gè)PMSGINFO結(jié)構(gòu),通過(guò)消息來(lái)處理自定義對(duì)象。 關(guān)于GETCALLBACK回調(diào)函數(shù)和PMSGINFO結(jié)構(gòu)的定義和實(shí)現(xiàn)方法,請(qǐng)查閱PDefine.h文件中的回調(diào)函數(shù)說(shuō)明和結(jié)構(gòu)說(shuō)明。8如果在第7步中定義了一個(gè)PMSGINFO結(jié)構(gòu),則在派生類(lèi)中重載基類(lèi)PBaseAct中的virtual LPPMSGINFOGetCallBackMsg()方法,返回指向PMSGINFO結(jié)構(gòu)的指針。如果在第7步中實(shí)現(xiàn)了GETCALLBACK回調(diào)函數(shù),則在派生類(lèi)中重載基類(lèi)PBaseact中的virtual GETCALLBACK* GetParseActFunPointer()方法,返回指向GETCALLBACK回調(diào)函 數(shù)的指針。這兩個(gè)函數(shù)你只需要重載一個(gè),建議重載GETCallBackMsg()方法,通過(guò)消息來(lái)處理指令對(duì)象。如果兩個(gè)函數(shù)都重載了,將優(yōu)先處理回調(diào)函數(shù)。9調(diào)用PDefine:SetUserGetObjectFunHook(),將在第6步中實(shí)現(xiàn)的GOCALLBACK鉤子函數(shù)的地址作為參數(shù)傳遞。六 在開(kāi)始一個(gè)任務(wù)之前的準(zhǔn)備工作PPQ.DLL會(huì)向DLL的外部傳遞一些很重要的消息,這些消息必需被響應(yīng),否則PPQ.DLL無(wú)法正常正作。另外,還有一些是必需賦值的靜態(tài)屬性,被定義在了PDefine類(lèi)中。1 初始化PDefine:rSMsgInfo結(jié)構(gòu)。2 實(shí)現(xiàn)回調(diào)函數(shù)GETPALCALLBACK,并將回調(diào)函數(shù)的地址賦給PDefine:pSGetFriendCallBackFun屬性。3 實(shí)現(xiàn)回調(diào)函數(shù)GETFILENCALLBACK,并將調(diào)函數(shù)的地址賦給PDefine:pSGetFileNCallBackFun屬性。4 為PDefine:szSelfFriendID屬性賦初值,表明自己的ID。5 為以下消息創(chuàng)建響應(yīng)函數(shù):OMSG_CREATE_NEW_OBJ,OMSG_CREATE_NEW_TASK,OMSG_ALL_CONNECT_END,OMSG_MISSION_END6 調(diào)用PDefine:SInitSocketStream()方法初始化Win Socket,使創(chuàng)建SOCKET連接成為可能。7 調(diào)用PDefine:SCreateTCPListenPort()方法創(chuàng)建TCP監(jiān)聽(tīng)端口。8 調(diào)用PDefine:SSetUserGetObjectFunHook()方法設(shè)定鉤子函數(shù)。9 為想建立連接的對(duì)方,建立PFriend對(duì)象,并填寫(xiě)上他ID、IP地址和TCP監(jiān)聽(tīng)端口號(hào)。 七 從URL下載一個(gè)文件最簡(jiǎn)單的任務(wù)就是從URL下載一個(gè)文件。PPQ.DLL封裝了通過(guò)HTTP下載的全過(guò)程,你想在自己的軟件中增加網(wǎng)絡(luò)螞蟻和FlashGet的功能嗎?不要著急,使用PPQ.DLL,你只需要調(diào)用幾個(gè)函數(shù),就可以實(shí)現(xiàn)自動(dòng)下載的過(guò)程。1 在堆中創(chuàng)建一個(gè)PRECVINFO結(jié)構(gòu)。LPPRECVINFO lprInfo=new PRECVINFO();2 初始化結(jié)構(gòu),這步是必需的,每創(chuàng)建一個(gè)PRECVINFO結(jié)構(gòu),就應(yīng)該調(diào)用以下的方法初始化結(jié)構(gòu)。memset(lprInfo,0,DWORD(&lprInfo-nPort)-(DWORD)lprInfo);3 設(shè)定URL地址。lprInfo-strSrvURL =/ptmini.exe;4 設(shè)定下載后文件被保存的路徑,如果缺省,文件將被保存在當(dāng)前目錄下。lprInfo-strSaveBasePath=d:;5 創(chuàng)建一個(gè)PTask對(duì)象,準(zhǔn)備開(kāi)始一個(gè)新的任務(wù)。PTask* pTask=new PTask();6 設(shè)定啟動(dòng)多少個(gè)線程同時(shí)下載。pTask-SetMaxThreadNo(10);7 將PRECVINFO結(jié)構(gòu)的地址賦給PTask對(duì)象。pTask-m_lprRecvInfo=lprInfo;8 開(kāi)始執(zhí)行一個(gè)HTTP下載任務(wù)。pTask-StartTask(TASK_HTTP_RECV);任務(wù)在執(zhí)行過(guò)程中會(huì)向PDefine:rSMsgInfo結(jié)構(gòu)中定義的窗體發(fā)送消息,以表明當(dāng)前的任務(wù)執(zhí)行狀態(tài)。任務(wù)結(jié)束后,窗體也會(huì)接收到消息以表明當(dāng)前任務(wù)是否已經(jīng)完成。關(guān)于這些消息的說(shuō)明,請(qǐng)查閱PDefine.h中的消息的說(shuō)明。 八 建立一個(gè)語(yǔ)音聊天想實(shí)現(xiàn)自己的IPPhone嗎?想和你在國(guó)外的朋友互訴一下衷腸嗎?不用再擔(dān)心昂貴的國(guó)際長(zhǎng)途費(fèi)用,寫(xiě)個(gè)小的程序,一切就OK啦。你會(huì)發(fā)現(xiàn),使用PPQ.DLL實(shí)現(xiàn)一個(gè)語(yǔ)音聊天非常簡(jiǎn)單。1 開(kāi)始一個(gè)聊天任務(wù),其中this-m_pFriend是一個(gè)已經(jīng)創(chuàng)建好的PFriend對(duì)象。PTask* pTask=new PTask();pTask-m_pFriend=this-m_pFriend;pTask-StartTask(TASK_TCP_CHAT);2 啟動(dòng)聲音播放設(shè)備PDefine:SPlaySound();3 初始化聲音捕捉設(shè)備PDefine:SGetSoundCaptureDeviceList(NULL);PDefine:SInitSoundCaptureDevice(NULL);PDefine:SGetSoundCaptureAvailableFormats(NULL);PDefine:SCreateSoundCaptureBuffer(NULL);4 設(shè)置捕捉到的聲音被傳遞給哪一個(gè)好友。PDefine:SSetSoundCaptureAcceptdFriend(this-m_pFriend);5 開(kāi)始聲音捕捉。PDefine:SRecordSound();經(jīng)過(guò)以上的步驟,一個(gè)語(yǔ)音聊天已經(jīng)被創(chuàng)建了,并且自動(dòng)地開(kāi)始捕捉聲音,一旦有一個(gè)有效的聲音被捕捉到,就會(huì)立即被傳給指定的好友,接收到的聲音被按照接收時(shí)的順序排在一個(gè)隊(duì)列中,聲音播放設(shè)備會(huì)自動(dòng)按照順序播放。實(shí)際上,你已經(jīng)可以同時(shí)和多人進(jìn)行聊天,每個(gè)人都可以同時(shí)和你說(shuō)話,但是在任意一個(gè)時(shí)刻你只能對(duì)其中一個(gè)人講話。在集成IP組播以后,會(huì)提供方法,以實(shí)現(xiàn)同時(shí)將聲音傳遞給多個(gè)好友。PPQ.DLL在語(yǔ)音的傳輸?shù)膶?shí)現(xiàn)上和其它程序?qū)崿F(xiàn)語(yǔ)音傳輸?shù)姆绞接泻艽蟮牟煌?。大部分程序在?shí)現(xiàn)語(yǔ)音傳輸時(shí)通常是啟用2個(gè)TCP連接來(lái)完成(UDP方式除外),一個(gè)TCP連接用來(lái)傳輸控制命令或消息,一個(gè)TCP連接用來(lái)專門(mén)傳輸聲音數(shù)據(jù),因?yàn)樗鼈兊穆曇魯?shù)據(jù)必需是連續(xù)傳輸?shù)?,即一旦啟?dòng)語(yǔ)音聊天,即使你沒(méi)有說(shuō)話,也會(huì)有連續(xù)不斷地?cái)?shù)據(jù)被傳送到連接方。PPQ.DLL通過(guò)一個(gè)簡(jiǎn)單的語(yǔ)音過(guò)濾功能,不再傳送靜音的數(shù)據(jù),以減少不必要的數(shù)據(jù)傳遞量。另外,PPQ.DLL采用的是對(duì)象的傳遞方式,它只通過(guò)一個(gè)TCP連接來(lái)實(shí)現(xiàn)聊天,不管是文字聊天還是語(yǔ)音聊天,采用的都是同一個(gè)連接,你可以在聊天的過(guò)程中,一邊進(jìn)行語(yǔ)音聊天,一邊通過(guò)聊天連接傳送其它的數(shù)據(jù),而彼此之間并不會(huì)互相干擾。 九 從另一個(gè)好友處下載一個(gè)文件通過(guò)在2個(gè)客戶端之間建立一個(gè)連接,來(lái)完成指定文件的傳送與接收,是P2P的基本功能。PPQ.DLL封裝了整個(gè)過(guò)程,采用了多線程,斷點(diǎn)續(xù)傳的方式來(lái)實(shí)現(xiàn)文件的傳送與接收,使處理標(biāo)準(zhǔn)和簡(jiǎn)單化。1 初始化開(kāi)始一個(gè)傳送或接收任務(wù)所必需的步驟LPPRECVINFO lprInfo=new PRECVINFO();memset(lprInfo,0,DWORD(&lprInfo-nPort)-(DWORD)lprInfo);lprInfo-strSaveBasePath=d:;PTask* pTask=new PTask();pTask-SetMaxThreadNo(5);pTask-m_lprRecvInfo=lprInfo;2 設(shè)定連接到哪一個(gè)好友,其中this-m_pFriend是一個(gè)已經(jīng)創(chuàng)建好的PFriend對(duì)象。pTask-m_pFriend=this-m_pFriend;3 設(shè)定想下載的文件的數(shù)字標(biāo)識(shí)pTask-m_dwFileID=100;4 開(kāi)始一個(gè)通過(guò)TCP來(lái)接收文件的任務(wù)。pTask-StartTask(TASK_TCP_RECV);與好友之間的連接被自動(dòng)地建立,并啟動(dòng)多線程來(lái)完成文件的接收。PPQ.DLL只有在連接被確定建立后,才會(huì)啟動(dòng)一個(gè)新的線程來(lái)接收數(shù)據(jù),并不向FlashGet那樣,只要有一個(gè)連接被建立,就會(huì)啟動(dòng)最大的線程個(gè)數(shù),去償試連接,結(jié)果經(jīng)常是多個(gè)連接無(wú)法被建立,而線程卻都被啟動(dòng)了,每個(gè)線程都在努力地償試連接。PPQ.DLL在采用TCP和HTTP方式下載時(shí),都遵循著這樣一個(gè)原則:先償試連接,等到連接被建立后才啟動(dòng)新的線程,等到開(kāi)始傳送有效數(shù)據(jù)后,才會(huì)去償試進(jìn)行下一個(gè)連接,以避免很多無(wú)效的線程被啟動(dòng)。 十PPQ.DLL的無(wú)關(guān)性協(xié)義傳輸PPQ.DLL的對(duì)象傳送并不是MFC和JAVA的序列化對(duì)象,它使用了一套比MFC和JAVA更為先進(jìn)的序列化對(duì)象的方式,在解碼時(shí)不但可以正確地將傳送時(shí)的對(duì)象還原出來(lái),而且可以在傳送的類(lèi)無(wú)法識(shí)別的情況下,自動(dòng)地還原成與傳送的類(lèi)最接近的一個(gè)基類(lèi)的對(duì)象。PPQ.DLL的解碼和編碼程序,采用純C+編寫(xiě),可以很容易地改寫(xiě)成其它語(yǔ)言,整個(gè)解碼和編碼過(guò)程不需要任何的語(yǔ)法分析,也不用對(duì)數(shù)據(jù)進(jìn)行掃描,所有編碼和解碼過(guò)程采用順序執(zhí)行過(guò)程,執(zhí)行速度非常快,而且整個(gè)的編碼和解碼程序編譯后只有幾K大小。 在開(kāi)發(fā)PPQ.DLL的初期,只是為了將P2P的具體連接過(guò)程和傳輸數(shù)據(jù)的過(guò)程封裝起來(lái),以簡(jiǎn)化P2P的開(kāi)發(fā),并且使彼此開(kāi)發(fā)的程序,可以在自定義傳輸協(xié)議的情況下互相通信,它的基本思路是采用對(duì)象作為基本信息單位來(lái)傳遞。TCP采用的是一種流式的數(shù)據(jù)傳送方式,因此對(duì)于接收方來(lái)講,在接收有效數(shù)據(jù)之前,必需明確地接收一些數(shù)據(jù),來(lái)表明其后的有效數(shù)據(jù)所表示的意義,這里暫且把表明其后有效數(shù)據(jù)意義的數(shù)據(jù),稱作指令,把指令后所傳送的有效數(shù)據(jù)稱為值,可以看出,實(shí)際的流式數(shù)據(jù)是由指令和值來(lái)構(gòu)成的。指令和值一起才能夠明確地表示出數(shù)據(jù)的有效意義,沒(méi)有指令的數(shù)據(jù),實(shí)際是無(wú)效的,因?yàn)闊o(wú)法明確地知道它所表示的意義。指令和值可以重復(fù)出現(xiàn)多次,并且值由字節(jié)構(gòu)成,每個(gè)字節(jié)由8位二進(jìn)制來(lái)表式,其長(zhǎng)度可以是任意的,沒(méi)有限制。一個(gè)或一組指令和值組合在一起,就構(gòu)成了指令對(duì)象。重復(fù)出現(xiàn)的一個(gè)或一組指令對(duì)象可以明確地表明希望接收方去完成某一種操作,這些指令對(duì)象和要完成的操作一起構(gòu)成了一個(gè)事務(wù),所以TCP的應(yīng)用實(shí)際是一種基于事務(wù)的處理。 MFC和JAVA都提供了非常完善的序列化對(duì)象方式,但可惜的是,彼此之間無(wú)法互用,MFC的對(duì)象只能由MFC來(lái)解析,JAVA也是一樣,因此,要想實(shí)現(xiàn)跨平臺(tái)操作,就不能使用它們的序列化對(duì)象方式。SOAP和XML也是一種很好地與平臺(tái)無(wú)關(guān)的傳輸協(xié)義,來(lái)標(biāo)準(zhǔn)化數(shù)據(jù)傳送時(shí)的格式,但它們都是對(duì)字符串來(lái)進(jìn)行操作,這也并不符合TCP傳輸二進(jìn)制流的概念。 如果將傳送數(shù)據(jù)作為字符串來(lái)表示,就不得不考慮不同平臺(tái)的字符編碼問(wèn)題,但是這種考慮與實(shí)際的數(shù)據(jù)傳送是相違背的,因?yàn)閭魉偷臄?shù)據(jù)實(shí)際都是以二進(jìn)制字節(jié)來(lái)傳送的。為了將傳送數(shù)據(jù)以二進(jìn)制字節(jié)方式來(lái)傳送,PPQ.DLL重新定義了一套序列化對(duì)象的方式,在序列化對(duì)象時(shí),將對(duì)象轉(zhuǎn)變成二進(jìn)制流來(lái)傳送,在反序列化時(shí),直接將二進(jìn)制流拷貝到對(duì)象相應(yīng)的屬性的緩沖區(qū)中,而不再以字符串的形式來(lái)出現(xiàn),避開(kāi)了不同平臺(tái)對(duì)字符編碼的問(wèn)題。PPQ.DLL的序列化和反序列化對(duì)象時(shí),無(wú)需定義任何的語(yǔ)法規(guī)則,也沒(méi)有定義任何的不可用字符,所有的數(shù)據(jù)均是以字節(jié)為單位來(lái)傳送和接收,在反序列化對(duì)象時(shí),不需要對(duì)接收數(shù)據(jù)進(jìn)行任何的掃描,也沒(méi)有使用循環(huán),所有操作均是順序完成,指令形成速度非??欤⑶铱梢宰詣?dòng)探測(cè)并丟棄未知指令對(duì)象和錯(cuò)誤的指令對(duì)象,即使接收數(shù)據(jù)中間出現(xiàn)錯(cuò)誤,仍然能夠跳過(guò)錯(cuò)誤的數(shù)據(jù),正確地接收后續(xù)的指令對(duì)象。將TCP的流式數(shù)據(jù)作為事務(wù)來(lái)處理的最大好處是,可以用一個(gè)DLL、OCX或COM等組件來(lái)封裝一個(gè)或多個(gè)事務(wù)的具體處理過(guò)程,所有的事務(wù)處理都是基于指令對(duì)象來(lái)進(jìn)行的處理,而不用去追究數(shù)據(jù)的來(lái)源。封裝后的事務(wù)可以直接被其他的開(kāi)發(fā)者調(diào)用,而不需要再為處理相同的事務(wù)去重復(fù)開(kāi)發(fā)程序,能更好地加快開(kāi)發(fā)過(guò)程,減少錯(cuò)誤發(fā)生的機(jī)率。這是PPQ.DLL的一個(gè)宗旨。 PPQ.DLL本身并沒(méi)有規(guī)定連接雙方應(yīng)該傳送的指令對(duì)象,它采用插件的形式,支持外部掛接任意多組指令對(duì)象,交由PPQ.DLL處理的數(shù)據(jù)會(huì)被PPQ.DLL自動(dòng)解析成指令對(duì)象,但是哪一些指令對(duì)象是開(kāi)發(fā)者需要的,卻是由開(kāi)發(fā)者自己來(lái)定義的。只有開(kāi)發(fā)者規(guī)定的指令對(duì)象,PPQ.DLL才會(huì)將指令對(duì)象提交給相應(yīng)的指令對(duì)象的處理程序,對(duì)于不可識(shí)別的指令對(duì)象,PPQ.DLL會(huì)自動(dòng)地丟棄。PPQ.DLL的序列化對(duì)象與MFC和JAVA的序列化對(duì)象的最大不同點(diǎn)在于,MFC和JAVA的序列化對(duì)象只能將對(duì)象還原成原來(lái)保存的類(lèi)的對(duì)象,即如果原來(lái)保存的類(lèi)不存在,則反序列化時(shí)會(huì)失敗,并拋出異常。PPQ.DLL的序列化對(duì)象在反序列化過(guò)程中,會(huì)自動(dòng)分析數(shù)據(jù)流所表示的類(lèi)是否可以識(shí)別,如果不能識(shí)別,則會(huì)查找該類(lèi)的基類(lèi),找到一個(gè)與數(shù)據(jù)流所表示的類(lèi)最為接近的一個(gè)基類(lèi),然后還原成該基類(lèi)的一個(gè)對(duì)象,調(diào)用該基類(lèi)對(duì)象的指令處理程序處理該指令,派生類(lèi)中的多余的不可識(shí)別的數(shù)據(jù)會(huì)被自動(dòng)丟棄。 PPQ.DLL的反序列化方式是進(jìn)行無(wú)關(guān)性協(xié)義傳輸?shù)囊粋€(gè)關(guān)鍵。 讓我們分析一下互聯(lián)機(jī)器進(jìn)行數(shù)據(jù)通訊的過(guò)程。以HTTP信息頭為例,在HTTP協(xié)議中規(guī)定HTTP的頭可以包含任意多行信息,每一行之間用rn結(jié)束,連續(xù)的2個(gè)rn表示整個(gè)HTTP信息頭結(jié)束,其后緊接著為有效數(shù)據(jù)。在HTTP的信息頭中,有一部分是每一個(gè)HTTP信息頭都必需包含的信息,如HTTP標(biāo)志,版本號(hào),返回代碼等,這個(gè)公共部分實(shí)際上就是一個(gè)基準(zhǔn)的類(lèi)。HTTP信息頭對(duì)于不同的服務(wù)器來(lái)講,它是允許擴(kuò)充的,可以加入一些對(duì)于該服務(wù)器能夠解析的其它標(biāo)志,來(lái)指示服務(wù)器采取一些特定動(dòng)作,這實(shí)際是對(duì)原基準(zhǔn)類(lèi)的一個(gè)擴(kuò)充,相當(dāng)于原基準(zhǔn)類(lèi)的一個(gè)派生類(lèi)。一個(gè)用戶傳遞了一個(gè)派生類(lèi)對(duì)象,服務(wù)器在接收到派生類(lèi)對(duì)象時(shí),如果它能夠識(shí)別這個(gè)派生類(lèi),表示它需要根據(jù)這個(gè)派生類(lèi)來(lái)執(zhí)行一些特定的操作,則在反序列化時(shí),會(huì)創(chuàng)建出這個(gè)派生類(lèi)的對(duì)象,通知服務(wù)器。如果服務(wù)器不識(shí)別這個(gè)派生類(lèi)對(duì)象,在反序列化時(shí),會(huì)自動(dòng)地查找該服務(wù)器可以識(shí)別的該類(lèi)的一個(gè)最接近的基類(lèi),這個(gè)基類(lèi)中所保存的數(shù)據(jù)將是這個(gè)服務(wù)器所關(guān)心的數(shù)據(jù),DLL會(huì)創(chuàng)建出這個(gè)基類(lèi),然后通知服務(wù)器。 PPQ.DLL的優(yōu)勢(shì)在什么地方呢?HTTP和XML等協(xié)議,其傳遞的都是字符串,接收方需要去解析字符串,找到自己感興趣的標(biāo)識(shí),再次分解字符串,得到指定的值。每一個(gè)接收方都必需去實(shí)現(xiàn)這個(gè)過(guò)程,當(dāng)然我們可以使用XML語(yǔ)法解析器將XML造型成對(duì)象來(lái)處理。讓我們關(guān)注一下XML造型成對(duì)象的過(guò)程,就會(huì)明顯地感受到它與PPQ.DLL的反序列化對(duì)象的本質(zhì)區(qū)別。HTTP和XML必需同時(shí)傳遞屬性名稱和屬性的值,因?yàn)榻邮辗皆诮馕鰧?duì)象時(shí),實(shí)際并不知道原來(lái)傳遞的內(nèi)容是什么,它只是將屬性名稱和值保存在哈希表中,屬性名相當(dāng)于哈希表的一個(gè)鍵,而屬性的值相當(dāng)哈希表中該鍵的值。當(dāng)接收方訪問(wèn)屬性時(shí),實(shí)際是在哈希表中搜索指定的鍵,然后返回給用戶該鍵所表示的值。從這里面,我們可以看出這樣一個(gè)問(wèn)題,接收方必需知道鍵的正確含義,否則它無(wú)法得到該鍵所表示的值。即然接收方已經(jīng)知道了鍵,那么為什么還需要去傳遞這個(gè)鍵呢?答案很簡(jiǎn)單,如果不傳遞鍵,它無(wú)法區(qū)分值應(yīng)該對(duì)應(yīng)到哪一個(gè)鍵。我們?cè)倏匆幌翽PQ.DLL是如何反序列化對(duì)象的。即然鍵對(duì)于接收方來(lái)講是已知的,它當(dāng)然可以作為對(duì)象中的一個(gè)屬性來(lái)存在,這和XML解析器將XML轉(zhuǎn)變成XML對(duì)象是一個(gè)道理。每一個(gè)XML的語(yǔ)法都可以作為一個(gè)指令類(lèi)或一個(gè)指令類(lèi)的派生類(lèi),而XML的屬性相當(dāng)于類(lèi)中的一個(gè)屬性,使用PPQ.DLL可以直接傳遞這個(gè)指令對(duì)象,PPQ.DLL序列化時(shí)并沒(méi)有傳遞屬性的名稱,它只把類(lèi)作為一個(gè)整體來(lái)傳遞,而類(lèi)對(duì)象的解析過(guò)程是由類(lèi)自己來(lái)定義的,因此,它仍然能夠被完整地解析出來(lái)。通過(guò)PPQ.DLL反序列化出來(lái)的類(lèi)對(duì)象是傳送方傳遞的類(lèi)或基類(lèi)對(duì)象的原形,它不但包含了屬性的值,并且也同時(shí)包含了與該對(duì)象相關(guān)的一切方法。我們?cè)趧?chuàng)建相關(guān)的協(xié)義規(guī)則時(shí),也同時(shí)制定了應(yīng)該如何解析該規(guī)則,XML和HTTP都只是傳輸了規(guī)則,卻無(wú)法傳輸規(guī)則的解析方法,而且這些規(guī)則必需是公開(kāi)規(guī)定的。而通過(guò)指令對(duì)象的傳遞,不但可以傳遞規(guī)則,而且同時(shí)也傳遞了解析該規(guī)則的方法,并且還能夠通過(guò)完全地封裝一個(gè)或幾個(gè)指令對(duì)象,來(lái)完全地封裝起規(guī)則,只對(duì)外提供訪問(wèn)的接口。 HTTP和XML等協(xié)義仍然需要一定的語(yǔ)法規(guī)則,在書(shū)寫(xiě)時(shí)也必需按照該規(guī)則來(lái)書(shū)寫(xiě),而PPQ.DLL的對(duì)象傳遞是一種真正地?zé)o關(guān)性協(xié)義,它沒(méi)有任何的語(yǔ)法規(guī)則來(lái)限制。 讓我們?cè)倏匆幌翽PQ.DLL為團(tuán)隊(duì)開(kāi)發(fā)所帶來(lái)的便利。在傳統(tǒng)的團(tuán)隊(duì)開(kāi)發(fā)模式中,雙方必需預(yù)先制定好要傳輸?shù)膮f(xié)義規(guī)則,然后開(kāi)始各自編寫(xiě)程序,如果一方需要改變或增加新的傳輸規(guī)則,他必需要通知其他的開(kāi)發(fā)者,這個(gè)協(xié)議已經(jīng)改變啦,你必需要相應(yīng)地改變解碼程序。但是如果采用了PPQ.DLL的對(duì)象傳送,即使有任何一方改變了傳輸規(guī)則,也不用互相通知,因?yàn)榻獯a程序不需要改變,而且PPQ.DLL的宗旨是封裝,它強(qiáng)調(diào)將任務(wù)劃分成若干指令來(lái)完成,各個(gè)指令的組合用來(lái)完成不同的任務(wù),而各指令的實(shí)現(xiàn)功能可以被完全地封裝在指令內(nèi)部,與指令的交互,只是通過(guò)接口來(lái)完成。 傳輸指令對(duì)象的好處是很多的,無(wú)法在這里一一例舉出來(lái),它是對(duì)傳統(tǒng)標(biāo)準(zhǔn)制定方式的一種挑戰(zhàn),使用這種方式,使所有的開(kāi)發(fā)者都可以參與到標(biāo)準(zhǔn)的制定過(guò)程中,而且這種標(biāo)準(zhǔn)就象滾雪球一樣,會(huì)在自然地使用過(guò)程中變得越來(lái)越龐大,越來(lái)越規(guī)范,越來(lái)越充實(shí),每一個(gè)開(kāi)發(fā)者都不必再?gòu)淖畹讓幼髌?,他們可以從前人的基礎(chǔ)之上直接繼承或派生出新的應(yīng)用,以最快地速度開(kāi)發(fā)出自己的程序。十一 PPQ.DLL的回調(diào)(鉤子)函數(shù)說(shuō)明* 函數(shù)名稱:*typedef PBaseAct* (WINAPI *GOCALLBACK)(LPCTSTR lpszClassID)*參數(shù):*LPCTSTRlpszClassID-唯一標(biāo)識(shí)一個(gè)類(lèi)的ID。*返回值:*PBaseAct*-返回新創(chuàng)建的對(duì)象。*說(shuō)明:*這是一個(gè)鉤子函數(shù)。通過(guò)這個(gè)函數(shù)將得到用戶自定義的PBaseAct派生類(lèi)的一個(gè)實(shí)例。注意:這是一個(gè)鉤子函數(shù),每一次的設(shè)定,都會(huì)被記錄下來(lái)。v1.02版以后,對(duì)算法進(jìn)行了改進(jìn),不再按照順序來(lái)逐個(gè)調(diào)用所設(shè)定的鉤子函數(shù),鉤子函數(shù)的執(zhí)行和安裝順序沒(méi)有直接關(guān)系,DLL會(huì)直接調(diào)用處理該ClassID的鉤子函數(shù)??梢栽谝粋€(gè)鉤子函數(shù)中同時(shí)處理多個(gè)ClassID,每一個(gè)ClassID都必需公布,并且明確各訴哪些ClassID是必需的,是完成同一個(gè)任務(wù),哪些是完成另一個(gè)任務(wù)所必需的,哪一些是可有可無(wú)的。這樣其他開(kāi)發(fā)者在設(shè)置鉤子函數(shù)時(shí),才能夠根據(jù)自己的需要來(lái)決定應(yīng)該使用哪些類(lèi)。舉例如下,其中Self1Act是自己定義的PBaseAct的派生類(lèi);USelf1Act是其它開(kāi)發(fā)者定義的PBaseAct的派生類(lèi),本地必需有這兩個(gè)類(lèi)的聲明。PBaseAct* WINAPI GlobalFunUserGetObject(LPCTSTR lpszClassID)if(memcmp(lpszClassID,B6FFC24C-7E13-11D0-9B47-00C04FC2F51D,PPQ_CLASS_ID_LEN)=0)/如果是自己定義的對(duì)象。return new Self1Act();else if(memcmp(lpszClassID,A9BEDC36-7E13-11D0-9B47-00C04FC2F51D,PPQ_CLASS_ID_LEN)=0)/加入對(duì)其他用戶創(chuàng)建的對(duì)象的支持。return new USelf1Act();return NULL;關(guān)于用戶自定義對(duì)象的健狀性問(wèn)題與惡意性攻擊的解決辦法:如果你但心其他用戶會(huì)發(fā)送一個(gè)非法的對(duì)象,但是使用了在你在函數(shù)中規(guī)定的ClassID,你大可不必?fù)?dān)心。DLL通過(guò)以下兩種方法來(lái)防止這種惡意攻擊行為:1當(dāng)雙方建立連接的時(shí)候,都必需通過(guò)一個(gè)身份驗(yàn)證的過(guò)程,這個(gè)過(guò)程中雙方傳遞的的指令對(duì)象是內(nèi)部定義好的指令對(duì)象,而且整個(gè)過(guò)程是外部不可干預(yù)的,只有通過(guò)身份驗(yàn)證的雙方才會(huì)建立起連接,也就是說(shuō),建立連接的雙方都是相互信任的。2如果通過(guò)身份驗(yàn)證的連接方要進(jìn)行惡意攻擊,DLL還會(huì)通過(guò)第二種辦法自動(dòng)丟棄這些錯(cuò)誤的指令,絕對(duì)不會(huì)造成程序的非法操作。DLL在發(fā)現(xiàn)惡意性攻擊時(shí),會(huì)記錄下攻擊的次數(shù),當(dāng)攻擊次數(shù)超過(guò)一定數(shù)量時(shí),會(huì)向用戶發(fā)出警告,告訴用戶發(fā)出惡意攻擊的連接方的ID,并自動(dòng)斷開(kāi)該連接。* * * * * * * * * * * * *函數(shù)名稱:* typedef PFriend* (WINAPI* GETPALCALLBACK)(LPCTSTR lpszFriendID)*參數(shù):* LPCTSTR lpszFriendID -好友的ID標(biāo)識(shí)*返回值:* PFriend* -指向好友對(duì)象的指針。*說(shuō)明:* 根據(jù)傳遞的好友ID返回指向具有該ID的PFriend對(duì)象的指針。* * * * * * * * * * * * *函數(shù)名稱:* typedef void (WINAPI *GETFILENCALLBACK)(DWORD dwFileID,PFriend* pFriend,CString* pstrFileN)*參數(shù):* DWORD dwFileID -請(qǐng)求的文件的數(shù)字標(biāo)識(shí)。* PFrined* pFriend -指向請(qǐng)求該文件的好友對(duì)象的指針。* CString* pstrFileN -指向保存文件數(shù)字標(biāo)識(shí)所對(duì)應(yīng)的實(shí)際文件名的指針。*返回值:* 無(wú)。*說(shuō)明:* 該函數(shù)將根據(jù)傳遞的dwFileID,來(lái)得到實(shí)際所對(duì)應(yīng)的文件名。文件名保存在pstrFileN對(duì)象中。 如果函數(shù)執(zhí)行后*pstrFileN=,表示獲取實(shí)際文件失敗。 可以在這個(gè)回調(diào)函數(shù)中對(duì)文件編號(hào)進(jìn)行校驗(yàn),決定好友是否有權(quán)得到該文件。 聲明: 對(duì)于文件采用數(shù)字標(biāo)識(shí)來(lái)表示,其最主要的目的是為了安全性,以及將來(lái)的擴(kuò)展。 數(shù)字標(biāo)識(shí)如何與實(shí)際的文件名相對(duì)應(yīng),可以采用很多種辦法,因此并沒(méi)有包含在 這個(gè)DLL中。 關(guān)于數(shù)字標(biāo)識(shí)與實(shí)際文件名的對(duì)應(yīng)關(guān)系,將提供一個(gè)專門(mén)的類(lèi)來(lái)實(shí)現(xiàn),這只是一種 解決辦法,大家可以自己去償試采用更好的辦法來(lái)解決這個(gè)問(wèn)題。 下面是一種建立數(shù)字標(biāo)識(shí)與實(shí)際文件名的對(duì)應(yīng)關(guān)系的方式: 采用數(shù)據(jù)庫(kù)中記錄的存儲(chǔ)方式來(lái)保存每一個(gè)數(shù)字標(biāo)識(shí)與實(shí)際文件名的對(duì)應(yīng)關(guān)系,每 一個(gè)數(shù)字標(biāo)識(shí)與實(shí)際文件名的對(duì)應(yīng)關(guān)系相當(dāng)于一條記錄,數(shù)據(jù)被集中保存在一個(gè)文 件中,每一個(gè)記錄均是定長(zhǎng)的,48個(gè)字節(jié)。 因?yàn)閿?shù)字標(biāo)識(shí)所表示的文件可以是本地機(jī)器上的任何一個(gè)目錄下的任何一個(gè)文件,并

溫馨提示

  • 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ù)網(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論