天天看點

利用Vista和WCF中強大P2P通信功能

在我們多數人考慮點對點 (P2P) 應用程式時,自然而然就會想到即時消息傳送應用程式、簡單檔案共享程式和遊戲。一般情況下,在我們考慮分布式應用程式設計時,已經習慣于預設選擇用戶端/伺服器模型,幾乎很少會想到 P2P 模型,哪怕是一閃而過的念頭,尤其是對于業務應用程式更是如此。我們為什麼都關注于用戶端/伺服器模型,其主要原因很簡單:P2P 應用程式的開發過程一慣都成本高昂且耗時過長。

  從傳統意義來說,P2P 應用程式開發所面臨的難題包括:需要開發用于消息交換的專用協定;必須查找并連接配接隐藏在“網絡位址轉換”(NAT) 或防火牆背後的某應用程式的執行個體;需要支援在廣域網 (WAN) 中定位各應用程式所需的慣常基礎結構。盡管上述難題可以克服,但已造成大量阻礙,這樣就導緻我們很多人都從未想過 P2P 應用程式所能提供的傑出的協作功能。

  這些阻礙将随着 Windows Vista™ 和附帶的 .NET Framework 3.0 版本的釋出而明顯改善。在将 Windows Vista 的增強功能與“對等名稱解析協定”(PNRP)、People Near Me (PNM) 和 Windows® Communication Foundation 中引進的 PeerChannel 功能相結合的情況下,我們又向 P2P 應用程式跨進了一大步。我個人期望在釋出 Windows Vista 之後,P2P 的舞台會更加絢麗多彩。

  Windows Vista 中的 P2P 開發是一個極其廣泛的主題,沒有任何一篇文章可以将其闡述完整。是以,我不會去嘗試完成這樣一個不可能的任務,而是會介紹 Windows Vista 中一些不同的 P2P 技術,并為您對 P2P 開發工作提供背景資料。

  除了假定您已基本了解 Windows 窗體之外,我還假設您已略微熟悉 Windows Communication Foundation 應用程式的編寫。

  P2P 基本原理:網格網絡

  在深入探讨具體的 P2P 技術之前,研究 P2P 應用程式的一些基本原理很重要。對初學者而言,P2P 應用程式是一個與該應用程式的其他執行個體直接相連的應用程式。在 P2P 語言中,該應用程式的每個執行個體都叫做一個節點。通常将這些節點連接配接和命名後的組合稱為網格。是以,推動 P2P 應用程式開發的技術經常被稱作網格技術。PNRP、PeerChannel(在 Windows Communication Foundation 中)和 PNM 都是 Windows Vista 中網格技術的例子。

  網格技術 所有 Windows Vista 網格技術所生成的網格在拓撲結構上都大緻相同。通常來講,網格拓撲是網格中各節點間連接配接模式的抽象展現。為了解釋清楚,請在腦海中設想一個網格。我敢斷定,您所設想的網格在某種程度上與圖 1 中所示的網格相似。

  

利用Vista和WCF中強大P2P通信功能

  圖 1 全連接配接網格

  圖 1 所示網格中四個節點中的每個節點都與網格中的其他所有節點相連。換言之,如果網格中有 N 個節點,則每個節點都保持 N-1 個連接配接。我們将達到此标準的網格視為全連接配接網格。全連接配接網格很少被用作适合的方法;要了解原因,讓我們注意一下各節點間的連接配接。

  網格中的節點基本上都使用現有的常用傳輸方式進行通信。與所有的現代作業系統一樣,Windows Vista 利用 TCP/IP 和 UDP 進行網絡通信。如果 TCP/IP 是全連接配接網格所選的傳輸方式,那麼由 N 個節點組成的全連接配接網格中的每個節點都必須建立或接收 N-1 個套接字。随着 N 值的增加,此模型顯然變得不可行。例如,如果假定一個 N=1000 的情況,那麼每個節點都将需要保持 999 個套接字,這簡直就行不通。

  要解決可伸縮性和 WAN 連接配接性的問題,您必須訴諸于部分連接配接的網格,如圖 2 中所示。顧名思義,部分連接配接網格中的節點隻與網格中的其他少量節點相連。就 P2P 來說,這些相鄰的節點被稱作鄰居。通常來說,部分連接配接網格對每個節點的資源需求更少,進而大幅提高了網格的可伸縮性。從理論上講,部分連接配接網格的規模可以擴大到包括全球所有計算機上的所有應用程式。

  

利用Vista和WCF中強大P2P通信功能

  圖 2 部分連接配接網格

  加入網格 節點加入網格的方式取決于所使用的網格技術,但通常來講,預期節點必須用網格名來解析網格中已有的一個或多個節點的實體位址。如果您假設一個部分連接配接網格,網格名的解析結果就是網格中可用實體位址的一個子集。在接收到網格中一個或多個實體節點的實體位址後,預期節點必須立即連接配接到這些位址中的一個、部分或全部位址。連接配接到網格之後,新添加的節點必須立即讓自己準備好響應來自其他預期節點的後續的網格名解析請求。

  網格名解析是一個複雜的主題。這種複雜性在很大程度上是因為,在許多情況下,網格名解析要依賴于一個或更多的其他網格。為清楚說明問題,請想一下美國郵政局使用的網格。再具體點說,假定我需要向我的朋友 Rusty 郵寄一個包裹。要郵寄這個包裹,我可能需要去一個郵局。如果我不知道距離我最近的郵局地點,我會到 Internet 上查找最近郵局的位址。從抽象意義上說,要“連接配接”到美國郵政局的網格需要我先通路所有網格中最大的網格(即 Internet)才能解析最近的節點的位址。換言之,您可以使用一個網格去解析包含在另一個網格中的位址。我将在本文的 PNRP 部分詳細讨論這個概念。

  與其他節點通信 一旦節點連接配接到某網格,它就可以通過以下兩種方式之一與其他節點進行通信:網格擴散(也稱多方消息傳送),或定向消息傳送。顧名思義,網格擴散是試圖将消息發送到網格中的所有節點。一般而言,網格中的某節點可通過将消息發送到它的所有鄰居而将消息傳播到其他所有節點。在接收到消息後,初始發送節點的鄰居負責将該消息轉發給它的鄰居,以此類推。相比之下,定向消息傳送指的是試圖将消息直接發送到網格中的某特定節點。在部分連接配接網格中,初始發送節點可能未與目标接收節點相連。如果真是這樣,則初始發送節點必須将消息發送給它的一個或多個鄰居。其中某個鄰居可能會與目标接收節點相連。如果是這樣,該鄰居就會将消息轉發給目标接收節點。如果不是這樣,則該鄰居會推測它的哪個鄰居自身可能會與目标接收節點相連。

  網格很少處于靜态。在多數 P2P 應用程式中,節點可能會頻繁加入和離開網格,可能是由于網絡連接配接變動引起,也可能是由于在使用即時消息傳送應用程式時,使用者啟動和終止應用程式引起。除了網格中的自然變動之外,多數網格技術都具備一些維護自身的機制。通常而言,網格維護的目标就是修複或調整網格以使其更高效或更穩健地運作。要注意到每個網格技術實作網格維護的方式都不同,這一點很重要。

顧名思義,PNRP 旨在基于網格名等要素來解析實體位址。PNRP 可供帶有 Advanced Networking Pack 的 Windows XP Service Pack 1 (SP1) 以及 Windows XP SP2 和 Windows XP Professional x64 Edition 使用。Windows Vista 也将附帶 PNRP 版本 2。從最簡單的層次看,PNRP 本身就是一個采用 Windows 服務形式的 P2P 應用程式,并且 PNRP 節點的網格專用于發現加入到其他網格中的節點的實體位址。

  PNRP 和 IPv6 PNRP 建構于 Internet 協定版本 6 (IPv6) 之上。由于 IPv6 對于多數開發人員而言還相當陌生,是以在讨論 PNRP 機制之前,非常有必要提及 IPv6 的至少一個重要方面。在 IPv6 中,位址是一個 128 位的值(這可能産生約 3.4×1038 種位址組合)。這種大小的 IPv6 位址池使 IPv6 的最重要功能之一 - 端對端尋址變為可能,即使這些位址被分割為多個子網并隐藏在 NAT 之後。

  PNRP 示例 PNRP 功能的原型、結構、錯誤代碼均在 Windows SDK 的 p2p.h 頭檔案中定義。如果某應用程式想要向 PNRP 注冊一個網格名,它必須用非托管代碼通過 Windows API 實作,或用托管代碼通過公共語言運作庫 (CLR) 的 P/Invoke 工具實作。目前,在 Windows API 的 PNRP 部分的 .NET Framework 中未包含托管包裝。但您可以通過使用 netsh 指令行實用程式來通路 PRNP。通過 netsh,您可以按以下所示向 PNRP 注冊一個新的 PNRP 名:

  c:/temp>netsh

  netsh>p2p pnrp peer

  netsh p2p pnrp peer>add 0.justinsmith

  Ok.

  指令行參數 0.justinsmith 即是 P2P 名。當此指令執行時,PNRP 基礎結構會生成一個 PNRP ID,将該 PNRP ID 與 P2P 名相關聯,并為該 PNRP ID 配置設定一個 IPv6 和 IPv4 位址。如果您通路另一台已安裝 PNRP 并已将其啟動的計算機,則可以用以下 netsh 指令解析網格名 0.justinsmith:

   netsh p2p pnrp peer>resolve 0.justinsmith

  Resolve started...

  Found: Comment: gonzo

  Addresses: [0000:0000:0000:0000:0000:0000:0000:0001]:8350 udp

  192.168.42.100:8350 tcp

  現在需要解釋一下該解析指令的輸出。首先,Comment 字段代表注冊了 0.justinsmith 的計算機名稱(我在 Muppets 的基礎上為我的計算機命名)。該字段從 netsh 自動填充,并且不能用作解析程序的一部分。其次,注意一下配置設定給該節點的 IPv6 和 IPv4 位址。這是 netsh 和允許通過 IPv4 網絡傳送 IPv6 通信量的 Teredo 轉移技術共同具備的一個功能。誠然,我隻是淺顯地闡述了 PNRP,但我已經表明了 PNRP 使我可以用 P2P 名來解析 IP 位址。

  PeerChannel

  Windows Communication Foundation 的主要優點之一就是,它為許多不同類型的分布式應用程式提供了一個通用的程式設計模型。例如,編寫一個基于 TCP/IP 通過二進制編碼消息進行通信的分布式應用程式所需的代碼與編寫一個基于 HTTP 通過符合 WS-* 的可互操作的消息進行通信的分布式應用程式所需的代碼驚人地相似。Windows Communication Foundation 的一個鮮為人知的功能就是它支援使用這同一個通用程式設計模型來建構 P2P 應用程式。由于 Windows Communication Foundation 對 P2P 應用程式的支援,可能會有人将其視為一種網格技術,但實際上,隻有 PeerChannel Windows Communication Foundation 子產品才專用于建構 P2P 應用程式。是以,PeerChannel 這個術語通常用于指代 Windows Communication Foundation 的 P2P 功能。無論 Windows Communication Foundation 中的 PeerChannel 指代的是什麼,它實際上消除了通常與 P2P 應用程式開發相伴的所有複雜性,并且在我看來,它是 P2P 應用程式開發領域的一個創新性突破。

  PeerChannel 網格 PeerChannel 網格是專為消息擴散而設計。但 PeerChannel 包含了可将消息傳播到網格的一部分而不是整個網格的機制。是以,更準确地說,PeerChannel 網格是專為多方消息傳送而設計。

  PeerChannel 網格的結構由每個節點所連接配接的鄰居數量所控制。為此,PeerChannel 網格會主動維護網格的結構。這種維護的作用就是使網格性能穩健并且分布均勻。更具體點說,網格中的節點會設法将連接配接的鄰居數保持在兩到七個之間。這些門檻值可使對本地節點的資源需求與保持網格穩健性之間取得平衡。

  如果某節點在進入網格時帶有三個鄰居,然後其中兩個鄰居離開網格,則該節點将開始一個維護周期以試圖擷取新的鄰居連接配接。同樣,如果一個節點連接配接的鄰居少于七個,則它将接受新連接配接,直到它具有七個鄰居連接配接時為止。當一個 PeerChannel 節點連有三個鄰居時,則認為它處于理想的連接配接狀态,但一個節點将接受多達七個鄰居,以便低于鄰居數最低門檻值的節點可以迅速獲得新的鄰居。應注意的是,您的應用程式代碼不能更改這些門檻值或對網格的維護實施任何控制,這一點很重要。這些細節問題完全由 PeerChannel 基礎結構逐個節點地處理。

  PeerChannel 提供了 PNRP 解析程式和自定義解析程式,以供用作預期節點發現網格中已有節點位址的方法。無論選擇哪個解析方法,主旨都是一樣的:将網格名傳遞到解析程式并接收網格中其他節點的 IP 位址清單。一旦解析程序生成位址清單,預期 PeerChannel 節點就并發連接配接到每個位址。當 PeerChannel 網格中已有的某節點收到其中一個連接配接請求時,它可以接受或拒絕該連接配接。如果接受該連接配接,則現有節點會向新連接配接的節點發送一條歡迎消息,消息中除了其他内容之外,還包含網格中其他節點的位址清單。如果拒絕該連接配接,則現有節點會向預期節點發送一條拒絕消息,消息中包含拒絕理由以及網格中其他節點的位址清單。

  這裡的重要一點是,網格名解析(通過 PNRP 解析程式或自定義解析程式執行)不是向 PeerChannel 中預期節點傳回位址清單的唯一方式。與将網格名解析作為預期節點擷取位址的唯一方法相比,此特性可使節點更快速地進入理想的連接配接狀态。此外,這一特性使網格中的節點可對節點擁有的鄰居數(這一因素會進而影響網格的穩健性)進行控制。

  PeerChannel 網格内的通信被調整為盡量減少重複性的消息傳遞。當網格中的某節點向該網格發送消息時,實際上是在向其鄰居發送消息。當收到消息後,每個鄰居都會檢驗該消息,然後将其轉發給自己的鄰居。如果一個 PeerChannel 節點從某鄰居收到消息,它不會将此消息轉發回該鄰居。此外,如果一個 PeerChannel 節點經常從某鄰居那裡收到先前已收到并處理過的消息,則與該鄰居的連接配接可能會在下一個維護周期中終止。這些功能将通過每個節點上的本地高速緩存來實作。在内部,PeerChannel 網格中的每個節點都會對 WS-Addressing 消息 ID 的值和傳送消息的鄰居的辨別符進行緩存處理。節點在決定向哪些鄰居傳送該消息時會檢查這個高速緩存。将這些功能相結合後,會将網格調整為以最低的重複率和網絡帶寬消耗來向網格中的各節點傳送消息。

  如前所述,PeerChannel 節點還可以将消息發送給網格中節點的子集。這可以通過向消息配置設定一個跳躍計數來實作,這實際上是跟蹤轉發消息所經由的節點數的方式。不要将這種機制與定向消息傳送相混淆,定向消息傳送是将消息傳送目标鎖定在某個特定節點。更确切地說,跳躍計數是模糊界定接收消息的節點數的方式。例如,如果一個 PeerChannel 節點(節點 A)有三個鄰居且在跳躍計數為 1 的情況下向網格發送一個消息,則該消息将被傳送到三個節點。同樣,如果節點 A 的每個鄰居也都有三個唯一鄰居且節點 A 在跳躍計數為 2 的情況下向網格發送一個消息,則該消息将被傳送到九個節點。但如果節點 A 的任一鄰居有共用的鄰居,則此數字将相應減少。

  從實體上說,跳躍計數在消息中被表示為标頭塊中的一個整數。當某節點收到帶有跳躍計數的消息時,它會檢查跳躍計數的值。如果該值大于零,節點會單調遞減此跳躍計數,然後将帶有遞減後的跳躍計數值的消息轉發給相應鄰居。如果所接收消息中包含的跳躍計數為 0,則不轉發該消息。另需注意的重要一點是,跳躍計數标頭塊被排除在消息簽名之外,是以更改這個值不會影響到應用于消息的數字簽名的完整性,而且會防止産生與重複生成數字簽名并将其序列化到消息相應部分中所關聯的開銷。

  PeerChannel 示例 讓我們用 PeerChannel 和 Windows 窗體來建構一個簡單的 P2P 應用程式,稱之為 PictureViewer。顧名思義,該應用程式的用途是允許網格中的所有節點可以檢視同一張圖檔。從高層次來說,建構此應用程式所需的步驟如下所示:

  1.定義基本的 Windows 窗體樣闆代碼。

  2.向窗體添加控件。

  3.定義必需的 Windows Communication Foundation 服務合約。

  4.編寫連接配接到網格和從網格接收消息所需的 Windows Communication Foundation 代碼。

  5.編寫向網格中其他節點發送消息所需的代碼。

圖 3 顯示了完成後的應用程式。步驟 1 和 2 是開發任何 Windows 窗體應用程式時所必需的步驟,是以我将不在這裡對其說明。對于任何 Windows Communication Foundation 應用程式,開發過程的第一步是定義服務合約。PeerChannel 要使用的服務合約類似于其他 Windows Communication Foundation 合約,隻不過 PeerChannel 需要所有的 OperationContractAttribute 批注都将 IsOneWay 執行個體屬性設定為 true。此屬性規定消息的接收方不應發送回複。如果想要接收方發送回複,可以将服務合約定義為雙向合約,但每個 OperationContractAttribute 批注仍必須将 IsOneWay 執行個體屬性設定為 true。就此例而言,我不會建立一個雙向合約(Windows SDK 中有幾個雙向合約的示例)。我要使用的合約如下所示:

  

[ServiceContract]

  interface IPictureViewer {

  [OperationContract(IsOneWay = true)]

  void SharePicture(Stream stream);

  }

利用Vista和WCF中強大P2P通信功能

  

  圖 3 PictureViewer P2P 應用程式

  請注意,SharePicture 接口方法用 OperationContractAttribute 屬性加以批注,并且 IsOneWay 執行個體屬性被設定為 true。SharePicture 操作将 System.IO.Stream 視為一個參數,因為此操作将被用于向網格中其他節點傳送圖檔的位元組。

  在定義了我們的服務合約後,現在就該添加 Windows Communication Foundation 代碼,該代碼會将我們的應用程式連接配接到 PeerChannel 網格并且被動等待來自網格的消息。首先,在窗體中實作新定義的服務合約。然後,定義類型 ServiceHost 的字段。所接收的消息将被發送到 frmPictureViewer 類型的單個執行個體。要表明此功能,我必須将正确的 ServiceBehavior 配置設定給 frmPictureViewer 類型。這兩個步驟如下所示。

  實施服務合同

   [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

  public partial class frmPictureViewer : Form, IPictureViewer

  {

  // 托管接收者

  ServiceHost host;

  // 接收消息時将要調用的方法

  public void SharePicture(Stream stream)

  {

  // 擷取圖像

  Image image = Bitmap.FromStream(stream);

  // 在窗體的圖檔框中顯示圖像

  pbView.SizeMode = PictureBoxSizeMode.StretchImage;

  pbView.Image = image;

  }

  ... // 為清晰起見省略其他成員

  }

  接下來,我必須對 ServiceHost 進行執行個體化,添加端點并開始偵聽外來的消息。由于我正在建構 Windows 窗體應用程式,是以實作此操作的邏輯位置就是窗體的構造函數,如下所示。

  嘗試加入網格和偵聽消息

   public frmPictureViewer()

  {

  InitializeComponent();

  StartReceiving();

  }

  private void StartReceiving()

  {

  // 定義網格名并設定與 PNRP 解析器的

  // 對等綁定

  Uri meshAddress = new Uri("net.p2p://pictureView");

  NetPeerTcpBinding binding = new NetPeerTcpBinding();

  binding.Resolver.Mode = PeerResolverMode.Pnrp;

  binding.Security.Transport.CredentialType =

  PeerTransportCredentialType.Password;

  binding.MaxReceivedMessageSize = 700000L;

  host = new ServiceHost(this);

  host.AddServiceEndpoint(typeof(IPictureViewer), binding,

  meshAddress);

  // 定義密碼并擷取數字簽名證書

  host.Credentials.Peer.MeshPassword = "JustinSmith";

  host.Credentials.Peer.Certificate = GetCertificate();

  // 嘗試聯結和偵聽消息

  host.Open();

  }

  此時,我已經完成了要連接配接到網格并偵聽消息所需的所有步驟。與标準的 Windows Communication Foundation 代碼相比,不同之處隻在于 Uri 的方案 (net.p2p)、所使用的綁定 (NetPeerTcpBinding) 以及所增添的基于密碼的安全性。請注意,我已選擇将網格密碼直接置于代碼中,這一點很重要。如果想要使網格密碼保密,請不要在您目前所使用的應用程式中如此操作。

  隻要調用了 ServiceHost.Open,我們的應用程式就會嘗試通過 PNRP 來解析網格名 (pictureView)。此時,我可以通過運作 netsh 指令以列出注冊的對等名稱來驗證我們的 PeerChannel 應用程式是否正在使用 PNRP。如果 PNRP 可以将網格名解析為一個或多個 IP 位址,則我們的應用程式将嘗試連接配接到這些節點。如果不是這樣,則該節點将成為網格中的第一個節點。如前所述,現有節點将通過發送歡迎消息或拒絕消息來接受或拒絕連接配接。這裡的重要一點是,這種情況有可能在對 ServiceHost.Open 的調用傳回後發生。

  将消息發送到其他節點 在共享圖檔之前,我必須首先加載圖檔。實作此操作所需的代碼是 Windows 窗體基本代碼:首先,對 OpenFileDialog 進行執行個體化,獲得一個 Stream,将該 Stream 轉換為 Image,然後通過 PictureBox.Image 屬性引用 Image。等一下,這不是 SharePicture 方法所執行的操作嗎?事實上,确實如此。從本質上說,要将圖像加載到 PictureBox 中,我隻需要調用 SharePicture 方法,将從 OpenFileDialog.OpenFile 傳回的 Stream 作為一個參數傳遞。

  要将包含圖檔的消息發送到網格中的其他節點,我必須編寫幾行代碼,但是此代碼與您在其他任何 Windows Communication Foundation 應用程式中編寫的代碼幾乎相同。起初,我需要在類型 ChannelFactory 和 IPictureViewer 的窗體中定義一些字段。接下來,我需要在窗體的構造函數中将這些變量執行個體化。這些步驟如下所示。

  建立發送基礎結構

   ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

  public partial class frmPictureViewer : Form, IPictureViewer

  {

  ChannelFactory channelFactory;

  IPictureViewer channel;

  public frmPictureViewer()

  {

  InitializeComponent();

  StartReceiving();

  }

  private void StartReceiving()

  {

  // 為清晰起見省略其他代碼

  channelFactory = new ChannelFactory(

  binding, new EndpointAddress(meshAddress));

  channelFactory.Credentials.Peer.MeshPassword = "JustinSmith";

  channelFactory.Credentials.Peer.Certificate = GetCertificate();

  channel = channelFactory.CreateChannel();

  }

  ... // 為清晰起見省略其他代碼

  }

  請注意,所使用的網格密碼和證書(用于建立消息的數字簽名)與設定 ServiceHost 時所用的必須是同一個。除此之外,此代碼要與非 PeerChannel Windows Communication Foundation 應用程式中所需的代碼相同。

  既然我已經建構了自己的發送基礎結構,我就可以使用它向網格中的其他節點發送消息。為此,我隻需為共享按鈕編寫一個事件處理程式即可,如下所示:

   private void btnShare_Click(object sender, EventArgs e)

  {

  using(MemoryStream stream = new MemoryStream())

  {

  Image image = pbView.Image;

  image.Save(stream, ImageFormat.Jpeg); // 将圖像存儲到 stream 中

  stream.Position = 0; // 複位位置

  channel.SharePicture(stream); // 向網格發送消息

  }

  }

  簡言之,PeerChannel 大大簡化了 P2P 應用程式的開發。PictureViewer 的完全功能版約有 150 行源代碼,其中大部分代碼專用于 Windows 窗體基礎結構。這個功能完全的應用程式包含了一個跳躍計數實作。

  People Near Me

  PNM 是內建在 Windows Vista 之中的一種網格技術,它允許鄰近的裝置組和人員組互相發現、連接配接、邀請并進行協作。PNM 特别适用于這樣一些任務:在咖啡店與鄰座其他幾個人一起玩遊戲;與同僚共享您的桌面;甚至連接配接到會議室中的投影儀,等等。PNM 提供的這些功能如此強大,我們有理由假設,一旦它被釋出,開發人員社群就将會找到新的、具有獨創性的方式來利用此技術。重要的是,要注意 PNM 是一項完全自選的網格技術,在預設情況下是關閉狀态。

  除其他應用程式之外,PNM 體系結構包含了一個稱為 p2phost.exe 的 P2P 應用程式。此程序運作時,将通過連接配接到其他計算機上 p2phost.exe 的執行個體來建立網格。通常而言,此網格的用途是定向消息傳送。更确切地說,PNM 用于解析本地節點并與這些本地節點的子集進行通信。PNM API 作為 Windows API 的一部分提供,并且多半程度上側重于配置 p2phost.exe 的行為。

  總的來說,PNM API 的主要類别包括函數、結構、事件和錯誤代碼,通過這些類别可以向 PNM 注冊應用程式、邀請其他人加入協作會話、啟動已注冊的應用程式、建立持久性合約并邀請不再屬于本地的聯系人。提要欄中的“真實環境中 People Near Me 的示例”将例示此過程。請注意,不支援應用程式使用 PNM 進行通信。就 PictureViewer 而言,這表示在提要欄中說明的 Tom 和 Harry 的 PictureViewer 執行個體之間傳遞的消息仍由 PeerChannel 來處理。

  結束語

  P2P 應用程式開發是一個涉及範圍非常廣泛的主題,并且對于多數開發人員而言還相當陌生。随着 Windows Vista 和 .NET Framework 3.0 的釋出,P2P 應用程式的傳統開發門檻将明顯降低。我相信,技術的進步(如 PNRP、IPv6)加上更具生産力的新型平台的問世(如 PeerChannel 和 PNM)将在 P2P 應用程式開發領域開創一個新時代。最終,應用程式将更具協作性,并提供我們起初隻能想像的一些功能。

繼續閱讀