1.P2P基本原理
在所有的P2P應用中,對等節點首先必須能夠彼此發現對方,一旦能夠找到提供P2P服務的計算機節點,就可以直接與它通信。例如,計算機A要下載某個MP3文件x,首先需要發現擁有文件x的P2P計算機節點,而后直接和該計算機節點通信,完成文件傳輸。P2P應用程序應該包括三個階段:發現,連接和通信。發現階段負責動態定位對等節點的網絡位置;連接階段負責在對等節點之間建立網絡連接;而通信階段負責在對等節點之間傳輸數據。
2.P2P資源發現演示
2.1 發布資源
同時開啟4個進程,模擬網絡上對等的4個計算機節點,如圖1所示。
為了便於描述,把這四個進程分別編號為進程A,進程B,進程C,進程D,各進程對應地址具體如下:
進程A:10.0.0.246 :50649
進程B:10.0.0.246 :50588
進程C:10.0.0.246 :50014
進程D:10.0.0.246 :50252
圖1 開啟4個對等節點進程
在上面4個P2P程序終端上,添加注冊一些資源,如圖2所示:
圖2 其中一個對等節點所添加的資源
2.2 搜索資源
選取進程A作為主體,搜索網絡中其他對等程序上的資源。例如,現在需要尋找歌曲《我的中國心》,在“種子”資源名編輯框中輸入“我的中國心”,單擊“搜索”按鈕,如圖3所示:
圖3 搜索”我的中國心“結果
因為主機上帶有虛擬網絡所以結果中每個進程有兩個IP地址,但實際上只有兩個進程含有“我的中國心”。在試驗中,只有進程B和進程C的節點上有《我的中國心》的種子資源,都被進程A成功地搜索到了!從進程A界面上的列表中,可以看到資源所在對等機的位置,還有發布時間信息。
3. 核心代碼的實現

1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.Net;
10 using System.Net.Sockets;
11 using System.Net.PeerToPeer;
12
13 namespace P2pResourceDiscovery
14 {
15 public partial class frmP2pResDiscovery : Form
16 {
17 PeerNameRegistration[] resNameRegistration = new PeerNameRegistration[100];
18 int seedCount = 0; //本地發布的種子數
19 public frmP2pResDiscovery()
20 {
21 InitializeComponent();
22 IPAddress[] ips = Dns.GetHostAddresses("");
23 tbxlocalip.Text = ips[0].ToString();
24 int port = new Random().Next(50000, 51000);
25 tbxlocalport.Text = port.ToString();
26 tbxResName.Text = "Res01";
27 }
28
29 private void btnRegister_Click(object sender, EventArgs e)
30 {
31 if (tbxResName.Text == "")
32 {
33 MessageBox.Show("請填寫要發布的資源名!", "提示");
34 return;
35 }
36 //將種子資源名注冊到雲中
37 PeerName resName = new PeerName(tbxResName.Text, PeerNameType.Unsecured);
38 resNameRegistration[seedCount] = new PeerNameRegistration(resName, int.Parse(tbxlocalport.Text));
39 resNameRegistration[seedCount].Comment = resName.ToString();
40 resNameRegistration[seedCount].Data = Encoding.UTF8.GetBytes(string.Format("{0}", DateTime.Now.ToString()));
41
42 //完成注冊
43 resNameRegistration[seedCount].Start();
44
45 seedCount++;
46 comboxSharelst.Items.Add(resName.ToString());
47 tbxResName.Text = "";
48 }
49
50 private void tbnRemove_Click(object sender, EventArgs e)
51 {
52 int index = comboxSharelst.SelectedIndex;
53 if (index == -1)
54 {
55 MessageBox.Show("請先選擇要撤銷的資源!", "提示");
56 return;
57 }
58 else
59 {
60 for (int i = 0; i < seedCount; i++ )
61 {
62 if (resNameRegistration[i].Comment == comboxSharelst.SelectedItem.ToString())
63 {
64 //撤銷資源
65 resNameRegistration[i].Stop();
66 comboxSharelst.Items.RemoveAt(index);
67 comboxSharelst.Text = "";
68 break;
69 }
70 }
71 }
72 }
73
74 private void tbnSearch_Click(object sender, EventArgs e)
75 {
76 if (tbxSeed.Text == "")
77 {
78 MessageBox.Show("請先填好要尋找的種子資源名!", "提示");
79 return;
80 }
81 lstViewOnlpeer.Items.Clear();
82 PeerName reseedIwant = new PeerName("0." + tbxSeed.Text);
83 PeerNameResolver myResolver = new PeerNameResolver();
84 PeerNameRecordCollection recColl = myResolver.Resolve(reseedIwant);
85 foreach (PeerNameRecord record in recColl)
86 {
87 foreach (IPEndPoint endP in record.EndPointCollection)
88 {
89 if (endP.AddressFamily.Equals(AddressFamily.InterNetwork))
90 {
91 ListViewItem item = new ListViewItem();
92 item.SubItems.Add(endP.ToString());
93 item.SubItems.Add(Encoding.UTF8.GetString(record.Data));
94 lstViewOnlpeer.Items.Add(item);
95 }
96 }
97 }
98 }
99 }
100 }