使用C#开发一个简单的P2P应用
尽管有许多P2P网络不需要索引服务器或中央服务器,各客户机之间可以互相直接通讯,但下面的图1还是显示了P2P网络的基本工作原理,一般来说,P2P概念中包含一台中央索引服务器,这台服务器并不存储有任何文件,它只存储有登录到该网络上的所有用户的信息、客户端的IP地址以及用户提供的供共享的文件,客户机和服务器使用简单的命令通过报路连接进行通讯。
当客户端A想要查找P2P网络上其他客户端提供共享的文件时,系统会执行下面的操作:
·客户端A以自己的用户名登录到索引服务器上。
·客户端A向服务器注册自己想提供给其他用户共享的文件,以便其他用户能够查找到这些文件。
·客户端A向服务器发出申请,查找与一定的输入模式相匹配的文件。
·索引服务器在其数据库中搜索给定的文件名,并将搜索到的如下的结果返回给客户端A:
·提供该文件的客户端,例如客户端B。
·该用户的IP地址。
·它搜索到的文件名。
一旦客户端A选择了下载选项,客户端A就使用搜索返回的IP地址与客户端B建立连接。
·一旦成功地建立起一个连接,就可以通知对方开始发送文件了。
·下载完成后,应当向索引服务器注册你得到的共享文件的拷贝。
这样的P2P网络可以用来共享任何类型的文件,它既可以用在局域网上,也可以作在互联网上。
当客户端A想要查找P2P网络上其他客户端提供共享的文件时,系统会执行下面的操作:
·客户端A以自己的用户名登录到索引服务器上。
·客户端A向服务器注册自己想提供给其他用户共享的文件,以便其他用户能够查找到这些文件。
·客户端A向服务器发出申请,查找与一定的输入模式相匹配的文件。
·索引服务器在其数据库中搜索给定的文件名,并将搜索到的如下的结果返回给客户端A:
·提供该文件的客户端,例如客户端B。
·该用户的IP地址。
·它搜索到的文件名。
一旦客户端A选择了下载选项,客户端A就使用搜索返回的IP地址与客户端B建立连接。
·一旦成功地建立起一个连接,就可以通知对方开始发送文件了。
·下载完成后,应当向索引服务器注册你得到的共享文件的拷贝。
这样的P2P网络可以用来共享任何类型的文件,它既可以用在局域网上,也可以作在互联网上。
![]() (图1) |
C#语言由于其对网络功能良好的支持,特别是内置地支持TCPListener和TCPClient这二个类,使得利用它开发P2P应用程序变得非常容易。下面就是一个使用C#开发的P2P应用的例子:
1
public MyTcpListener(int port) : base(port)
2
3
public void StopMe()
4
{
5
if ( this.Server != null )
6
7
}
8
}
9
10
public class Transfer
11
{
12
MyTcpListener tcpl;
13
14
public Transfer()
15
{
16
OptionsLoader ol = new OptionsLoader();
17
int port = 8081;
18
if (ol.Port > 0)
19
{
20
port = ol.Port;
21
}
22
else
23
{
24
port = 8081;
25
}
26
27
this.tcpl = new MyTcpListener(port);
28
}
29
30
public void TransferShutdown()
31
32
33
public void ListenForPeers()
34
{
35
try
36
{
37
38
Encoding ASCII = Encoding.ASCII;
39
40
41
tcpl.Start();
42
43
44
while (true)
45
{
46
// 在有连接之前,Accept将处于阻塞状态
47
Socket s = tcpl.AcceptSocket();
48
NetworkStream DataStream = new NetworkStream(s);
49
50
String filename;
51
Byte[] Buffer = new Byte[256];
52
DataStream.Read(Buffer, 0, 256);
53
filename = Encoding.ASCII.GetString(Buffer);
54
StringBuilder sbFileName = new StringBuilder(filename);
55
StringBuilder sbFileName2 = sbFileName.Replace("", "");
56
FileStream fs = new FileStream(sbFileName2.ToString(), FileMode.Open, FileAccess.Read);
57
BinaryReader reader = new BinaryReader(fs);
58
byte[] bytes = new byte[1024];
59
int read;
60
while((read = reader.Read(bytes, 0, bytes.Length)) != 0)
61
{
62
DataStream.Write(bytes, 0, read);
63
}
64
reader.Close();
65
DataStream.Flush();
66
DataStream.Close();
67
}
68
}
69
catch(SocketException ex)
70
{
71
MessageBox.Show(ex.ToString());
72
}
73
}
74
75
public void DownloadToClient(String server, string remotefilename, string localfilename)
76
{
77
try
78
{
79
TcpClient tcpc = new TcpClient();
80
Byte[] read = new Byte[1024];
81
82
OptionsLoader ol = new OptionsLoader();
83
int port = 0;
84
if (ol.Port > 0)
85
{
86
port = ol.Port;
87
}
88
else
89
{
90
// 缺省的端口号,可以设置为使用的端口号
91
port = 8081;
92
}
93
94
95
// 尝试与服务器连接
96
IPHostEntry IPHost = Dns.Resolve(server);
97
string []aliases = IPHost.Aliases;
98
IPAddress[] addr = IPHost.AddressList;
99
100
IPEndPoint ep = new IPEndPoint(addr[0], port);
101
tcpc.Connect(ep);
102
103
// 获得流对象
104
Stream s = tcpc.GetStream();
105
Byte[] b = Encoding.ASCII.GetBytes(remotefilename.ToCharArray());
106
s.Write( b, 0, b.Length );
107
int bytes;
108
FileStream fs = new FileStream(localfilename, FileMode.OpenOrCreate);
109
BinaryWriter w = new BinaryWriter(fs);
110
111
// 读取流对象,并将其转换为ASCII码
112
while( (bytes = s.Read(read, 0, read.Length)) != 0)
113
{
114
w.Write(read, 0, bytes);
115
read = new Byte[1024];
116
}
117
118
tcpc.Close();
119
w.Close();
120
fs.Close();
121
}
122
catch(Exception ex)
123
{
124
throw new Exception(ex.ToString());
125
}
126
}
127
}
128
}
129

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129
