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. 核心代码的实现
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }