首页 | IT新闻 | 硬件 | 操作系统 | 开发 | 网络编程 | 数据库 | 热门框架 | 网络安全 | 组网 | 建站指南 | 网页制作 | 特效 | 实用技巧 | 服务器 | 办公 | QQ | 探索 | 社区

  • 技术部落
  • 部落首页 > 程序开发 > C/C#/C++ > 正文
  • 关于VC写P2P软件的一些思考
      2007-5-29  来源:CSDN  编辑:Jsbulo  热度:

      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的方法也就不多说了