p2p即pear to pear ,就是点对点体系结构。它实际了主机间的直接通信,减轻了服务器的负担。我对利用p2p实现像电驴、BT下载、百度下吧这样的软件的一些问题跟大家交流一下。
1. 有没有服务器,服务器到底做些什么工作。
目前来讲很多p2p软件是有中心服务器的,其主要工作是记录每个节点(边缘主机)共享的文件列表及相关信息,或者换句话说,它记录的是共享了某个文件的主机列表(ip及相应的端口号)。客户端(相对于中心服务器)要请求某个文件时,只需先向中心服务器请求到该文件的主机列表,再向每台主机发送传送请求。当然,在客户端请求的文件的同时,它的信息也被记录到中心服务器中了。相比传统的C/S模式,中心服务器的负担轻很多了。
是不是说一定需要中心服务器呢?答案是否定的。假定这样一种情况:某台主机A共享了一些文件,想让互联网上的朋友得到他。主机A要怎么做呢?其中一种方法就是:将自己机子的信息做成一个文件(命名为FILE_A),该文件包括:主机A的ip,以及为传送数据而用的端口号,文件名。然后将该文件发布到网上,主机A的朋友就可以通过该文件的内容联上主机A与其通信完成文件的传输。主机A的朋友(假设是B、C、D)联接是A时,在传输数据的同时,更新FILE_A(此时A、B、C、D每人都有一份最新的FILE_A),在合适的时候将最新的FILE_A发布到网上,供别的人使用。
显然,没了中心服务器问题变得复杂得多。下面我们只讨论有中心服务器的情况。
2. 边缘主机(客户端?)做了些什么
我们先把这个概念弄清楚。按照客户端、服务器的定义,只要是发送请求的就是客户端、只要是响应请求的就是服务器端。客户与服务器只是一个相对概念,所以在这里我们把中心服务器就叫服务器,把其它主机叫做边缘主机。
边缘主机一方面响应其它边缘主机的请求,一方面跟据自己的需要去请求其它边缘主机。首先,我们看看,边缘主机有些什么信息。边缘主机维护着一张自己共享的文件的列表,该列表包括文件的位置(只要有文件的位置就可能得到储如文件的大小,类型之类的信息),以及文件名。其它边缘主机向该主机请求那个文件时,只需将该文件的文件名发给它,它就知道知道如何去定位那个文件。边缘主机还有张从中心服务器那得到的共享了某个文件的主机列表。通过该列表的内容就可能向各个主机请求自己要的文件。
3. 关于多点传输与断点传输
我们先看一段在VC下传送文件的代码(摘于VCKBASE杂志13期,作者:Vicken Simonian 翻译:DY)
下面给出服务器端代码:
void SendFile()
{
#define PORT 34000 /// Select any free port you wish
AfxSocketInit(NULL);
CSocket sockSrvr;
sockSrvr.Create(PORT); // Creates our server socket
sockSrvr.Listen(); // Start listening for the client at PORT
CSocket sockRecv;
sockSrvr.Accept(sockRecv); // Use another CSocket to accept the connection
CFile myFile;
myFile.Open("C:\\ANYFILE.EXE", CFile::modeRead | CFile::typeBinary);
int myFileLength = myFile.GetLength(); // Going to send the correct File Size
sockRecv.Send(&myFileLength, 4); // 4 bytes long
byte* data = new byte[myFileLength];
myFile.Read(data, myFileLength);
sockRecv.Send(data, myFileLength); //Send the whole thing now
myFile.Close();
delete data;
sockRecv.Close();
}
以下是客户端代码
void GetFile()
{
#define PORT 34000 /// Select any free port you wish
AfxSocketInit(NULL);
CSocket sockClient;
sockClient.Create();
// "127.0.0.1" is the IP to your server, same port
sockClient.Connect("127.0.0.1", PORT);
int dataLength;
sockClient.Receive(&dataLength, 4); //Now we get the File Size first
byte* data = new byte[dataLength];
sockClient.Receive(data, dataLength); //Get the whole thing
CFile destFile("C:\\temp\\ANYFILE.EXE",
CFile::modeCreate | CFile::modeWrite | CFile::typeBinary);
destFile.Write(data, dataLength); // Write it
destFile.Close();
delete data;
sockClient.Close();
}
仔细观查这段代码,你会发现只要设置与保存好载入点就可以实现多点传输与断点续传。当然用什么算法去实现直接影响传送速率。
4. 关于边缘主机间的连接
因为并不是所有的边缘主机都在公网上,所以涉及到局域网地址到公网地址的转换。网上有很多穿透NAT的方法也就不多说了
个人水平有限,如果有什么说得不妥的,欢迎一起切磋
我的e-mail: [email protected]
我的qq:93318762
本文地址:http://com.8s8s.com/it/it679.htm