摘 要: 介紹了Microsoft用于構(gòu)建分布式面向服務(wù)架構(gòu)的新一代框架WCF(Windows Communication Foundation)的體系結(jié)構(gòu)與技術(shù)要素;同時(shí)分析了對(duì)等網(wǎng)絡(luò)(Peer-to-Peer network)的基本原理和網(wǎng)格化特性。在分析WCF和P2P網(wǎng)絡(luò)優(yōu)點(diǎn)的基礎(chǔ)上開發(fā)了一個(gè)即時(shí)通信軟件,總結(jié)了使用.NET平臺(tái)開發(fā)P2P應(yīng)用的基本步驟,闡述了對(duì)等網(wǎng)絡(luò)是開發(fā)P2P應(yīng)用的理想平臺(tái)。
關(guān)鍵詞: WCF; SOA; 對(duì)等網(wǎng)絡(luò); 網(wǎng)格化; 即時(shí)通信
對(duì)等網(wǎng)絡(luò)P2P(Peer to Peer)也稱為對(duì)等連接,是一種新的通信模式。P2P網(wǎng)絡(luò)的一個(gè)重要目標(biāo)就是讓所有的客戶端都能提供資源,包括帶寬、存儲(chǔ)空間和計(jì)算能力。因此,當(dāng)有節(jié)點(diǎn)加入且對(duì)系統(tǒng)請(qǐng)求增多,整個(gè)系統(tǒng)的容量也增大。這是目前客戶機(jī)/服務(wù)器(C/S)結(jié)構(gòu)不能實(shí)現(xiàn)的。
P2P的應(yīng)用開發(fā)是分布式網(wǎng)絡(luò)開發(fā)的一種典型應(yīng)用,軟件開發(fā)難度較大,WCF(Windows Communication Foundation)作為微軟基于SOA所推出的.NET平臺(tái)下的新一代框架產(chǎn)品集成了現(xiàn)有技術(shù)的優(yōu)點(diǎn)。本文將綜合利用對(duì)等網(wǎng)絡(luò)和WCF實(shí)現(xiàn)一個(gè)即時(shí)通信軟件,采用WCF快速、便捷地開發(fā)P2P應(yīng)用。
1 WCF概述
WCF整合了Com+、.Net Remoting、WebService等現(xiàn)有技術(shù)的優(yōu)點(diǎn),提供了一種構(gòu)建安全可靠的分布式面向服務(wù)系統(tǒng)的統(tǒng)一的框架模型,使軟件開發(fā)人員在開發(fā)分布式應(yīng)用時(shí)變得更加輕松[1]。
1.1 面向服務(wù)
WCF是一套面向服務(wù)的框架。服務(wù)是指暴露在外的一系列功能的集合,面向服務(wù)則是指一套構(gòu)建“面向服務(wù)程序”的抽象原則以及最優(yōu)方法[2]?;赪CF的程序設(shè)計(jì)考慮更多的是提供和使用服務(wù)。
WCF擁有一個(gè)非常靈活的分層體系結(jié)構(gòu),它的目標(biāo)是在單個(gè)框架中提供編碼、托管、消息傳遞模式、網(wǎng)絡(luò)連接、安全性和互操作性,這有助于簡化分布式應(yīng)用程序的開發(fā)[3]。
1.2 WCF的編程模型
WCF服務(wù)是通過端點(diǎn)通信的。WCF服務(wù)的端點(diǎn)充當(dāng)與其他應(yīng)用程序通信的網(wǎng)關(guān)。它是發(fā)送或接收消息的位置,包含交換消息所需的所有信息。端點(diǎn)由地址、綁定以及契約三部分組成[4],如圖1所示。
地址制定該服務(wù)所駐留的位置,它表示為URL形式。綁定描述了WCF服務(wù)如何與客戶端應(yīng)用程序通信。契約是對(duì)WCF服務(wù)所提供功能的聲明。契約公開服務(wù)的接口、類、方法和變量,以使客戶端應(yīng)用程序能夠訪問和使用它們。
2 P2P對(duì)等網(wǎng)絡(luò)
在P2P對(duì)等網(wǎng)絡(luò)中,將由對(duì)等節(jié)點(diǎn)組成的集合稱為網(wǎng)格(mesh)。任何一個(gè)對(duì)等節(jié)點(diǎn)都可以通過指定終節(jié)點(diǎn)(Endpoint)的方法來加入到一個(gè)網(wǎng)格中。網(wǎng)格是彼此之間可以相互通信并由唯一的網(wǎng)格ID標(biāo)識(shí)的對(duì)等節(jié)點(diǎn)的命名集合。網(wǎng)格中的活動(dòng)節(jié)點(diǎn)發(fā)布其網(wǎng)格名稱,以便其他節(jié)點(diǎn)可以找到它們。
解析程序服務(wù)可以獲取網(wǎng)格ID,然后返回與向該特定網(wǎng)格ID注冊(cè)的節(jié)點(diǎn)對(duì)應(yīng)的地址列表。解析程序保持已注冊(cè)地址的列表,此列表是它通過讓網(wǎng)格中的每個(gè)節(jié)點(diǎn)向該服務(wù)注冊(cè)而創(chuàng)建的。
對(duì)等解析程序(PNRP)負(fù)責(zé)將網(wǎng)格ID解析為網(wǎng)格中節(jié)點(diǎn)的終節(jié)點(diǎn)地址[5]。在打開一個(gè)對(duì)等節(jié)點(diǎn)后,它會(huì)使用對(duì)等解析程序?qū)⒕W(wǎng)格ID解析為網(wǎng)格中其他對(duì)等節(jié)點(diǎn)的地址列表。這會(huì)創(chuàng)建一個(gè)由互連節(jié)點(diǎn)組成的網(wǎng)格,從而允許通過網(wǎng)格傳播消息。
3系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
3.1系統(tǒng)總體設(shè)計(jì)
P2P應(yīng)用程序的設(shè)計(jì)與普通分布式應(yīng)用程序不同,在設(shè)計(jì)時(shí)必須考慮到應(yīng)用程序本身既是服務(wù)的提供方同時(shí)也是服務(wù)的調(diào)用方。軟件整體結(jié)構(gòu)如圖2所示[6]。
每個(gè)加入到P2P對(duì)等網(wǎng)絡(luò)節(jié)點(diǎn)的客戶端可以通過EndPoint來加載WCF的服務(wù)契約并發(fā)布出去,但是整個(gè)對(duì)等網(wǎng)絡(luò)中沒有中央服務(wù)器的存在,所以節(jié)點(diǎn)與節(jié)點(diǎn)之間相互發(fā)現(xiàn)和通信比較困難,P2P對(duì)等網(wǎng)絡(luò)通過稱為PNRP的名稱解析的服務(wù)來解決這樣的問題。
3.2 服務(wù)端程序的設(shè)計(jì)
服務(wù)端主要的功能是創(chuàng)建一個(gè)CustomPeerResolverService類型的ServiceHost代理,啟用對(duì)等解析程序(PNRP),還負(fù)責(zé)提供服務(wù)主機(jī)的基址,該基址在配置文件(App.config)中進(jìn)行配置。經(jīng)過配置之后,服務(wù)便可以由客戶端的計(jì)算機(jī)在該基址訪問。具體代碼如下:
using System.ServiceModel.PeerResolvers;
//添加對(duì)等名稱解析協(xié)議服務(wù)
……
CustomPeerResolverService cprs;
//聲明自定義對(duì)等解析程序服務(wù)的變量
ServiceHost host; //聲明服務(wù)代理類
……
cprs=new CustomPeerResolverService(); //初始化變量
host=new ServiceHost(cprs);
在配置文件(App.config)定義一個(gè)終節(jié)點(diǎn),使客戶端可以與服務(wù)進(jìn)行通信。使用NetTcpBinding進(jìn)行綁定。
App.config配置如下:
<endpoint address="net.tcp://localhost/P2PChatServer" binding="netTcpBinding"… ></endpoint>
經(jīng)過配置之后,服務(wù)便可以由客戶端在 net.tcp://localhost/P2PChatServer處訪問。
3.3 客戶端加入網(wǎng)格
要實(shí)現(xiàn)P2P對(duì)等網(wǎng)絡(luò)中的節(jié)點(diǎn)相互通信,首先需要?jiǎng)?chuàng)建和注冊(cè)同級(jí),其他同級(jí)需要查找和訪問已注冊(cè)的同級(jí)。
需要特別注意的是網(wǎng)格中的每臺(tái)計(jì)算機(jī)既可以作為客戶端又可以作為服務(wù)器,那么設(shè)計(jì)所要實(shí)現(xiàn)的契約時(shí),應(yīng)將契約的回調(diào)契約指定為其自身。這樣無論是調(diào)用方還是被調(diào)用方都能夠?qū)崿F(xiàn)相同的操作,使得每臺(tái)計(jì)算機(jī)既能充當(dāng)客戶端又能成為服務(wù)端[6]。創(chuàng)建契約的代碼如下:
[ServiceContract(CallbackContract=typeof(IChatService))]
//將回調(diào)契約定義為本身
public interface IChatService
{
[OperationContract(IsOneWay=true)]
void DoSomeWork; //實(shí)現(xiàn)相應(yīng)的功能
}
使用WCF中的DuplexChannelFactory<T>泛型類創(chuàng)建一個(gè)雙向通道來實(shí)現(xiàn)雙向調(diào)用。使用該通道的CreateChannel()方法來創(chuàng)建通信通道的一個(gè)實(shí)例。整個(gè)對(duì)等名稱解析過程是由netPeerTcpBinding綁定封裝的,在創(chuàng)建通道的同時(shí),會(huì)在網(wǎng)格中注冊(cè)節(jié)點(diǎn),使得節(jié)點(diǎn)加入網(wǎng)格[6]。代碼如下:
InstanceContext context=new InstanceContext(this);
//上下文實(shí)例
Factory=new DuplexChannelFactory<IChatChannel>(context,"ChatEndPoint");
//創(chuàng)建雙工通信
Channel =Factory.CreateChannel(); //創(chuàng)建通道
3.4 網(wǎng)格中的計(jì)算機(jī)獲取節(jié)點(diǎn)標(biāo)識(shí)
當(dāng)網(wǎng)格內(nèi)有新的節(jié)點(diǎn)加入或退出時(shí)必須發(fā)送一個(gè)消息,這樣新的節(jié)點(diǎn)能查找到網(wǎng)格內(nèi)其他的節(jié)點(diǎn)。只有網(wǎng)格內(nèi)所有的節(jié)點(diǎn)有一個(gè)唯一的標(biāo)識(shí),才能實(shí)現(xiàn)對(duì)特定節(jié)點(diǎn)服務(wù)的調(diào)用,實(shí)現(xiàn)網(wǎng)格中客戶端點(diǎn)對(duì)點(diǎn)的相互通信。因此在編寫客戶端服務(wù)契約時(shí)必須包含獲取網(wǎng)格節(jié)點(diǎn)的方法以及提供節(jié)點(diǎn)加入或退出網(wǎng)格的事件處理代碼。
通過DuplexChannelFactory<T>創(chuàng)建的雙向通信能夠調(diào)用客戶端服務(wù)契約的方法,當(dāng)有新的節(jié)點(diǎn)加入網(wǎng)格時(shí)通過調(diào)用通道實(shí)例中的Join()方法將節(jié)點(diǎn)的標(biāo)識(shí)傳遞給網(wǎng)格內(nèi)其他節(jié)點(diǎn)。
由于在服務(wù)端App.config文件中定義了統(tǒng)一的基地址,所以對(duì)通道方法的調(diào)用是對(duì)網(wǎng)格內(nèi)所有節(jié)點(diǎn)的調(diào)用,因此網(wǎng)格內(nèi)其他節(jié)點(diǎn)就可以發(fā)現(xiàn)新加入的節(jié)點(diǎn)。具體實(shí)現(xiàn)的方法如下:
delegate void UserJoined(stringname);//聲明加入網(wǎng)格代理
static event UserJoined NewJoin; //定義加入網(wǎng)格事件
public void Join(stringmemberName)
{
if(NewJoin!=null)
{
NewJoin(memberName);
}
}
…
Channel.Join(this.userName)
當(dāng)有節(jié)點(diǎn)退出網(wǎng)格時(shí),與加入網(wǎng)格時(shí)一樣聲明一個(gè)退出網(wǎng)格事件代理,然后調(diào)用通道實(shí)例中的Leave()方法,退出網(wǎng)格;具體實(shí)現(xiàn)代碼與加入網(wǎng)格相似。
網(wǎng)格中節(jié)點(diǎn)之間消息的傳遞也可以聲明一個(gè)消息發(fā)送事件代理,在發(fā)送時(shí)可以加入自身的標(biāo)識(shí)作為參數(shù),以便其他人能夠識(shí)別。
4 系統(tǒng)的測(cè)試與運(yùn)行
系統(tǒng)的開發(fā)工具選擇Visual Studio 2010,程序編譯通過后,首先打開即時(shí)通信服務(wù)端軟件,然后單擊開始,服務(wù)啟動(dòng)成功,如圖3所示。
在兩臺(tái)客戶端計(jì)算機(jī)上分別運(yùn)行即時(shí)通信客戶端軟件并且輸入用戶名,點(diǎn)擊Join按鈕后節(jié)點(diǎn)會(huì)在網(wǎng)格中注冊(cè)并獲取網(wǎng)格中其他節(jié)點(diǎn)的標(biāo)識(shí),此時(shí)兩臺(tái)計(jì)算機(jī)作為兩個(gè)節(jié)點(diǎn)成功加入到網(wǎng)格中。在圖4中,一臺(tái)計(jì)算機(jī)成功地接收到了另一臺(tái)計(jì)算機(jī)自身登錄名稱和它所發(fā)送的消息。
本文介紹了如何使用WCF來開發(fā)P2P應(yīng)用程序。P2P應(yīng)用程序開發(fā)成本低并且擁有較好的并發(fā)處理能力,適用于小規(guī)模的網(wǎng)絡(luò),維護(hù)容易;但是對(duì)等網(wǎng)絡(luò)同時(shí)也存在一些不足和缺點(diǎn),如資源分享紊亂、管理較難、安全性較低等問題。雖然還存在著一些問題和不足,但P2P對(duì)等網(wǎng)絡(luò)依然是開發(fā)點(diǎn)對(duì)點(diǎn)應(yīng)用的一個(gè)理想平臺(tái)。
參考文獻(xiàn)
[1] 閆冰.基于WCF的分布式應(yīng)用開發(fā)[J].電腦知識(shí)與技術(shù),2008,3(1):68-70.
[2] 孫耀.基于WCF的網(wǎng)格化信息管理系統(tǒng)的研究與實(shí)現(xiàn)[D]. 長春:東北師范大學(xué),2009.
[3] 程湯培. 基于WCF的即時(shí)通信軟件的設(shè)計(jì)與實(shí)現(xiàn)[J]. 電腦編程技巧與維護(hù),2008(4):24-40.
[4] 陳茹. WCF框架下分布式系統(tǒng)的集成技術(shù)研究[D].大連:大連海事大學(xué),2010.
[5] 羅小平.基于PNRP協(xié)議的PeerChannel共享存儲(chǔ)模型的研究與應(yīng)用[D].成都:西南石油大學(xué),2011.
[6] 王麗麗,戴迪,王成江.Windows對(duì)等網(wǎng)絡(luò)上P2P應(yīng)用程序的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)與信息技術(shù),2009(3):36-40.