互聯網點對點通信(P2P)

 摘自: http://www.cnblogs.com/zhili/archive/2012/09/14/p2p_pnpr.htmlhtml

 很遺憾,目前看了下代碼,我測試只是作到了本地p2p.git

 

 

[C# 網絡編程系列]專題八:P2P編程

 

引言:程序員

前面的介紹專題中有朋友向我留言說介紹下關於P2P相關的內容的,首先本人對於C#網絡編程也不是什麼大牛,由於能力的關係,也只能把本身的一些學習過程和本身的一些學習過程當中的理解和你們分享下的,下面就進入正題——P2P(Peer to Peer)編程編程

 

1、P2P的介紹緩存

 首先,如今你們熟知的BT、電驢、迅雷、QQ、MSN和PPlive等都是基於P2P方式實現的軟件,而且對等聯網(Peer to Peer,P2P)將是互聯網的發展方向,所以對於P2P技術的瞭解顯得很是的重要,下面就來介紹下P2P架構:安全

在P2P技術以前,咱們全部的網絡應用都採用C/S或者B/S架構來實現的,然而在以前C/S架構的應用程序中,客戶端軟件向服務器發出請求,服務器而後對客戶端請求作出響應,在這種狀況下,若是客戶端越多,此時服務器的壓力就越大。然而採用P2P技術實現的每臺計算機既是客戶端,也是服務器,他們的功能都是對等的。對於安裝了P2P軟件(如迅雷,QQ等)的計算機加入一個共同的P2P網絡,網絡中的節點之間能夠直接進行數據傳輸和通訊。服務器

1.1 P2P架構和C/S架構的比較網絡

C/S架構有下面的缺點(其實上面的簡單介紹中也講到過):多線程

1. 服務器負擔太重。當大量用戶訪問C/S系統的服務器時,服務器經常會出現網絡堵塞等現象,這時候,咱們可能會經過增長投資提升服務器的硬件性能架構

2. 系統穩健性和服務器關聯密切。指的是——若是服務器出現了問題時,整個系統的運行將會癱瘓(感受是面向對象中常常強調的原則——低耦合原則)

然而P2P具備下面的特色:

1.對等模式

P2P系統中的客戶端可以同時扮演客戶端和服務器的角色,使兩臺計算機之間可以不經過服務器直接進行信息分享(QQ中當好友在線的時候發信息時,相信此時是不須要通過服務器轉發的,只有當給離線好友發送消息時,此時應該會先把消息發送到服務器端存儲起來,當好友再次登陸的時候,會和服務器進行鏈接,服務器會進行判斷是否是給這個用戶的信息來決定是否轉發,QQ軟件的實現屬於混合型P2P結構的, 這個會在後面的P2P系統分類中介紹。)

注:括號中都是我我的的一些理解,若是有什麼說錯的地方請你們及時更正我,這樣我會及時的更新以避免誤導你們,謝謝你們監督。

2. 網絡資源的分佈式存儲

在C/S架構中,全部客戶端都直接從服務器下載全部數據資源,這樣勢必會加劇服務器的負擔,而P2P則改變了以服務器爲中心的狀態,使每一個節點能夠先從服務器上個下載一部分,而後再相互從對方或者其餘節點下載其他部分。採用這種方式,當大量客戶端同時下載時,就不會造成網絡堵塞現象了。

 

1.2 P2P系統的分類

使用P2P技術的系統分爲兩類:(1)單純型P2P——沒有專用的服務器。安裝了P2P軟件的各個計算機能夠直接通訊

              (2)混合型P2P——有專用的服務器,此時的服務器通常叫索引服務器,此服務器與C/S架構下的服務器不一樣,在C/S架構下全部資源都存儲在服務器中,全部傳遞的信息都要通過服務器,而在混合型P2P系統中的索引服務器僅僅起到協調和擴展的功能,資源不是所有存儲在服務器上,而是分佈在各個電腦上,安裝了P2P軟件的電腦開始所有和索引服務器鏈接,以便告知本身監聽的IP地址和端口號,而後再經過索引服務器告訴其餘與本身鏈接的電腦,每臺計算機的鏈接和斷開都經過服務器通知網絡上有聯繫的計算機,這樣就減輕了每臺計算機搜索其餘計算機的負擔,可是信息的傳遞仍是經過點對點的方式來完成(這裏能夠以QQ爲例,當咱們電腦上安裝了QQ這類P2P軟件時,安裝了QQ這類軟件的計算機就會加入一個P2P網絡,而且登錄的時候都會與索引服務器創建鏈接,經過鏈接來告訴服務器本身的IP地址和端口號,當咱們找一個好友聊天時,此時本身的計算機和好友的計算機都會與服務器端口鏈接,可是要互相發送消息,本身的計算機必須知道好友計算機的IP地址和端口號才能夠通訊,這樣的工做正是經過索引服務器來告知對方的--指的是告訴本身的計算機好友的計算機的IP地址和端口號,告訴好友的計算機本身的IP地址和端口號,這樣雙方就能夠不經過服務器直接通訊了。)

 

1.3 主流P2P應用分類

P2P 網絡應用大體能夠分爲三類—— 1. 文件共享類,例如迅雷,BT等軟件都是文件共享類的應用

                 2. 即時通訊類,例如QQ,MSN等軟件都是屬於即時通訊類

                 3. 多媒體傳輸類,例如在線視頻直播軟件,PPlive等軟件

從上面的分類能夠看出,如今網絡上流行的軟件都採用了P2P技術來實現的, 可是它們的實現確定不是單純的只採用P2P技術來實現的, 而是採用多種技術來實現的, 在下一專題中將介紹利用TCP,UDP和P2P等技術來實現相似QQ的一個即時通訊程序,但願經過此程序能夠綜合前面專題介紹的內容以及幫助你們對QQ等軟件的實現原理有了解。

 

2、P2P的基本原理

在前面咱們對P2P的一些知識進行的簡單的介紹, 經過前面的介紹相信你們對P2P的技術有了必定的瞭解,可是要本身開發一個P2P的應用固然必須瞭解P2P技術的實現原理的,下面就介紹下P2P實施的基本原理。

安裝了P2P軟件後,首先雙方要進行通訊,必須可以發現對方(指的就是知道對方的IP地址和端口號),一旦發現了對方後才能夠進行通訊,因此P2P應用程序通常分爲發現、鏈接和通訊3個階段。 發現階段負責動態定位通訊方的網絡位置;鏈接階段負責在雙方創建網絡鏈接,通訊階段負責在雙方之間傳輸數據。

 2.1 發現階段

一臺計算機要和另一臺計算機通訊,必須知道對方的IP地址和監聽端口,不然就沒法向對方發送消息。在以前的C/S架構中,服務器的IP地址通常固定不變的,而且提供服務的計算機域名也通常不會改變,因此爲了方便客戶端訪問,一些Web服務器在DNS(DNS其實就是域名和IP地址的一個映射)中進行了註冊,客戶機能夠利用域名解析機制將服務器域名解析爲IP地址,而後在P2P應用中,各個對等節點(計算機或資源)能夠隨時加入和隨時離開,而且對等節點的IP地址也不是固定的,因此不能採用DNS的機制來獲取P2P架構中的對等節點的信息。

目前,在單純型P2P中,針對如何發現對等節點,各類P2P技術採用的協議和標準都不同,微軟在.net 支持對等名稱解析協議(Peer name Resolution Protocol, PNRP),該協議能夠發現對等節點的信息,經過無服務器的解析功能將任何資源解析爲一組IP地址和端口號,在後面的實現的簡單程序用的就是這個協議來完成發現階段的。

2.2 鏈接和通訊階段

 完成對等節點的發現後,接下來就能夠根據須要,選擇TCP、UDP或者其餘協議完成數據傳輸。若是選擇TCP,則須要先創建鏈接,再利用該鏈接傳輸數據,關於TCP的內容能夠查看我以前的專題;若是選擇UDP,則無須創建鏈接,直接在對等節點之間通訊就能夠了。

3、.net平臺對P2P編程的支持

 以前在發現階段也介紹了.Net平臺對P2P編程的支持的,而後微軟幫咱們已經封裝好了對PNRP協議的實現,這些類在System.Net.PeerToPeer命名空間裏(微軟如今不少東西都幫咱們封裝了,這樣能夠方便咱們開發應用程序,感受微軟的作的東西都是這樣,把程序的實現都幫咱們作好了,咱們開發程序的時候只要關注業務邏輯就行了的, 這樣作固然有好處也有壞處的, 我以爲好處就是縮短軟件的開發週期,讓花更多的時間去實現軟件真真的業務邏輯方面的東西,很差的地方就是如今的程序員就不能叫程序員,因此園子裏面有不少人都稱碼農,這些我本身的觀點了)

3.1 對等名稱解析協議(PNRP)

PNRP能夠完成對等名稱的註冊和解析(能夠和DNS對比來理解)。

3.1.1 基本概念

第一個介紹的是對等名稱的概念,咱們將每個網絡資源(包括計算機,P2P應用程序、視頻、Mp3或其餘文檔等資源)抽象爲對等節點,對等節點名稱固然就是對等節點的名稱。對等節點名稱簡稱爲對等名,分爲安全的和不安全的兩種形式,不安全的名稱僅由文本字符串組成,任何人均可以註冊一個相同的不安全對等名稱;安全的由一個公鑰/私鑰(表明惟一)對支持,因此使用PNRP註冊時,不會受到欺騙,對等名稱的格式以下:

Authority.Classifier

Authority的值取決於該名稱的安全類型。對於不安全的類型,Authority爲單字符「0」,而對於安全的對等名稱,Authority由40個十六機制字符組成

Classifier是用戶定義的用於標誌對等節點的字符串,最大長度爲150個Unicode字符。例如,對等名稱0.PeerNametest1就是一個不安全的對等名稱。

第二個概念就是雲(Cloud)的概念,安裝了相同P2P軟件的計算機會加入一個共同的P2P網絡中,才能相互識別各自擁有的資源並順利進行P2P通訊。微軟PNPR協議將這個P2P網絡稱爲「雲」。雲是指一組能夠經過P2P網絡相互識別的對等節點及其上資源的集合。雲中的全部對等節點均可以解析註冊到該雲中的其餘任何資源所在的位置(IP+Port),一個對等節點上的某個資源能夠同時註冊到多個雲中。

PNPR目前使用了兩種雲——本地雲和全局雲。一個對等名稱若註冊到連接一本地雲,就意味着只有同一本地網絡上的其餘對等節點能夠解析該名稱。而註冊到全局雲上的對等名稱則容許IPv6互聯網的任何對等節點解析。

注:全局雲是基於IPv6協議的,並不支持IPv4,若是不存在IPv6地址,則不會出現全局雲,也沒法加入全局雲。因爲如今網上絕大多數應用使用的仍然是IPv4的地址,因此咱們一般的P2P編程還用不到全局雲,而只能使用默認的本地雲。

3.1.2 名稱註冊

任何資源要被網絡上的其餘計算機識別到,首先必須註冊進P2P網絡,名稱註冊就是將包含對等節點信息的對等名稱發佈到雲中,以便其餘對等節點解析。一個資源若是註冊到雲中後,就能夠被雲中的其餘對等節點解析和訪問。

關於名稱註冊的具體內容,在後面的P2P的程序中也會使用的, 相信你們能夠經過代碼來進一步理解名稱的註冊,這裏就先介紹到這裏的

3.1.3 名稱解析

名稱解析是指利用對等名稱獲取到雲中資源所在對等節點的IP地址和端口號的過程(和DNS解析原理同樣)。PNPR名稱解析僅可以註冊到雲中的其餘對等節點資源,而不能發現自身註冊的資源

PNPR協議沒有使用索引服務器,因此爲了完成解析,雲中的每一個對等節點都存儲一些PNRP ID的緩存記錄。PNPR緩存中的都含有PNPR ID和應用程序的IP地址和端口號。名稱解析的步驟爲——首先在本地計算機對等節點的緩存中查找目標資源,若是沒有,則在緩存中的臨近節點查看,這樣循環下去,直到找到目標資源所在的對等節點位置。

3.2 PeerToPeer命名空間

上面主要介紹了PNPR協議的工做過程(至關因而理論部分了),下面就介紹下.net 爲咱們封裝好PNPR的類的使用。這裏就簡單指明幾個經常使用類的使用,並附上MSDN的連接,你們能夠直接點連接進行查看詳細內容,由於後面的P2P程序中也有具體的使用,因此這裏就不一一列出來了。

類名

MSDN連接

Peer

http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.collaboration.peer.aspx

 

Cloud

http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.cloud.aspx

PeerName

http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peername.aspx

 

PeerNameRecord

http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peernamerecord.aspx

 

PeerNameRegistration

http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peernameregistration_members(v=VS.90).aspx

 

PeerNameResolver

http://msdn.microsoft.com/zh-cn/library/system.net.peertopeer.peernameresolver.aspx

 

 這些類基本上從類名均可以大體知道他們的用途的,因此在這裏就沒有一一介紹的,只是附上了MSDN的連接。

4、實現P2P應用程序

以上介紹了那麼多P2P的相關的知識,主要是爲了實現一個自定義的P2P應用程序作準備的,這裏就簡單實現了資源發現的一個程序。

核心代碼:

 對等名稱的註冊代碼:

複製代碼
 // 註冊資源
        private void btnRegister_Click(object sender, EventArgs e)
        {
            if (tbxResourceName.Text == "")
            {
                MessageBox.Show("請輸入發佈的資源名!", "提示");
                return;
            }

            // 將資源名註冊到雲中
            // 具體資源名的結構在博客有介紹
            PeerName resourceName = new PeerName(tbxResourceName.Text, PeerNameType.Unsecured);
            // 用指定的名稱和端口號初始化PeerNameRegistration類的實例
            resourceNameReg[seedCount] = new PeerNameRegistration(resourceName, int.Parse(tbxlocalport.Text));
            // 設置在雲中註冊的對等名對象的其餘信息的註釋
            resourceNameReg[seedCount].Comment =resourceName.ToString();
            // 設置PeerNameRegistration對象的應用程序定義的二進制數據
            resourceNameReg[seedCount].Data = Encoding.UTF8.GetBytes(string.Format("{0}", DateTime.Now.ToString()));
            // 在雲中註冊PeerName(對等名)
            resourceNameReg[seedCount].Start();
            seedCount++;
            comboxSharelist.Items.Add(resourceName.ToString());
            tbxResourceName.Text = "";
        }
複製代碼

名稱解析代碼(搜索資源):

複製代碼
  // 搜索資源
        private void btnSearch_Click(object sender, EventArgs e)
        {
            if (tbxSeed.Text == "")
            {
                MessageBox.Show("請先輸入要尋找的種子資源名", "提示");
                return;
            }

            lstViewOnlinePeer.Items.Clear();
            // 初始化要搜索的資源名
            PeerName searchSeed = new PeerName("0." + tbxSeed.Text);
            // PeerNameResolver類是將節點名解析爲PeerNameRecord的值(即將經過資源名來查找資源名所在的地址,包括IP地址和端口號)
            // PeerNameRecord用來定於雲中的各個節點
            PeerNameResolver myresolver = new PeerNameResolver();

            // PeerNameRecordCollection表示PeerNameRecord元素的容器
            // Resolve方法是同步的完成解析
            // 使用同步方法可能會出現界面「假死」現象
            // 解決界面假死現象能夠採用多線程或異步的方式
            // 關於多線程的知識能夠參考本人博客中多線程系列我前面UDP編程中有所使用
            // 在這裏就不列出多線程的使用了,朋友能夠本身實現,若是有問題能夠留言給我一塊兒討論
            PeerNameRecordCollection recordCollection = myresolver.Resolve(searchSeed);
            foreach (PeerNameRecord record in recordCollection)
            {
                foreach(IPEndPoint endpoint in record.EndPointCollection)
                {
                    if (endpoint.AddressFamily.Equals(AddressFamily.InterNetwork))
                    {
                        ListViewItem item = new ListViewItem();   
                        item.SubItems.Add(endpoint.ToString());
                        item.SubItems.Add(Encoding.UTF8.GetString(record.Data));
                        lstViewOnlinePeer.Items.Add(item);
                    }
                }
            }
        }
複製代碼

運行結果截圖:
爲了演示資源發現的效果,因此同時開啓了本程序的3個進程來模擬網絡上對等的3個計算機節點,當在資源名中輸入資源後會在分享下列表中顯示出本地分享的資源,同時在P2P網絡上的其餘計算機能夠經過資源名稱搜索該資源,將獲得的資源名稱和發佈時間顯示在ListView控件中,下面是程序的運行結果:

5、總結

到這裏P2P編程的介紹就結束了, 本專題只是簡單演示了一個資源發現的程序,資源發現是P2P的核心技術,正是由於P2P技術實現了互聯網範圍的資源發現,才使得它被普遍應用,像咱們常常用的下載工具——迅雷,迅雷就是典型採用P2P技術的應用程序,當咱們在迅雷頁面中輸入「愛情公寓3」(至關於本專題中種子文本框填的資源名)而後點擊搜索後迅雷會自動啓動「狗狗搜索」並顯示資源連接列表,當咱們點擊鏈接就能夠進行下載了。不過迅雷確定不是使用微軟的PNPR,而是迅雷自主研發的與PNPR做用同樣的協議——都是完成解析網絡資源的地址的做用,固然,迅雷軟件中也採用了其餘的一些技術,如搜索引擎等。

但願本專題能夠幫助你們對P2P技術有所瞭解,若是有任何的問題均可以經過留言的方式來一塊兒討論,在下一個專題中將介紹實現一個相似QQ的程序。

 

源碼附上:http://files.cnblogs.com/zhili/P2PResourceDiscovery.zip ,但願以爲有幫助的朋友能夠推薦下。謝謝支持

 

 

 
 
77
1
 
(請您對文章作出評價)
 
« 上一篇: VSTO之旅系列(一):VSTO入門
» 下一篇: 我對博客園的建議
posted @ 2012-09-14 15:00 Learning hard 閱讀( ...) 評論( 82) 編輯 收藏
相關文章
相關標籤/搜索