转 c#开发一个简单的p2p应用

尽管有许多p2p网络不需要索引服务器或中央服务器,各客户机之间可以互相直接通讯,但下面的图1还是显示了p2p网络的基本工作原理,一般来说,p2p概念中包含一台中央索引服务器,这台服务器并不存储有任何文件,它只存储有登录到该网络上的所有用户的信息、客户端的ip地址以及用户提供的供共享的文件,客户机和服务器使用简单的命令通过报路连接进行通讯。  当客户端a想要查找p2p网络上其他客户端提供共享的文件时,系统会执行下面的操作:

   ·客户端a以自己的用户名登录到索引服务器上。

   ·客户端a向服务器注册自己想提供给其他用户共享的文件,以便其他用户能够查找到这些文件。

   ·客户端a向服务器发出申请,查找与一定的输入模式相匹配的文件。

   ·索引服务器在其数据库中搜索给定的文件名,并将搜索到的如下的结果返回给客户端a:

    ·提供该文件的客户端,例如客户端b。

    ·该用户的ip地址。

    ·它搜索到的文件名。
一旦客户端a选择了下载选项,客户端a就使用搜索返回的ip地址与客户端b建立连接。

   ·一旦成功地建立起一个连接,就可以通知对方开始发送文件了。

   ·下载完成后,应当向索引服务器注册你得到的共享文件的拷贝。

  这样的p2p网络可以用来共享任何类型的文件,它既可以用在局域网上,也可以作在互联网上。


(图1)

c#语言由于其对网络功能良好的支持,特别是内置地支持tcplistener和tcpclient这二个类,使得利用它开发p2p应用程序变得非常容易。下面就是一个使用c#开发的p2p应用的例子: 

public mytcplistener(int port) : base(port)
{

}
public void stopme()
{
if ( this.server != null )
{
this.server.close();
}
}
}
public class transfer
{
mytcplistener tcpl;
public transfer()
{
optionsloader ol = new optionsloader();
int port = 8081;
if (ol.port > 0)
{
port = ol.port;
}
else
{
port = 8081;
}
this.tcpl = new mytcplistener(port);
}

public void transfershutdown()
{
tcpl.stopme();
}
public void listenforpeers()
{
try
{

encoding ascii = encoding.ascii;

tcpl.start();

while (true)
{
// 在有连接之前,accept将处于阻塞状态
socket s = tcpl.acceptsocket();
networkstream datastream = new networkstream(s);
string filename;
byte[] buffer = new byte[256];
datastream.read(buffer, 0, 256);
filename = encoding.ascii.getstring(buffer);
stringbuilder sbfilename = new stringbuilder(filename);
stringbuilder sbfilename2 = sbfilename.replace("/", "//");
filestream fs = new filestream(sbfilename2.tostring(), filemode.open, fileaccess.read);
binaryreader reader = new binaryreader(fs);
byte[] bytes = new byte[1024];
int read;
while((read = reader.read(bytes, 0, bytes.length)) != 0)
{
datastream.write(bytes, 0, read);
}
reader.close();
datastream.flush();
datastream.close();
}
}
catch(socketexception ex)
{
messagebox.show(ex.tostring());
}
}
public void downloadtoclient(string server, string remotefilename, string localfilename)
{
try
{
tcpclient tcpc = new tcpclient();
byte[] read = new byte[1024];
optionsloader ol = new optionsloader();
int port = 0;
if (ol.port > 0)
{
port = ol.port;
}
else
{
// 缺省的端口号,可以设置为使用的端口号
port = 8081;
}

// 尝试与服务器连接
iphostentry iphost = dns.resolve(server);
string []aliases = iphost.aliases;
ipaddress[] addr = iphost.addresslist;
ipendpoint ep = new ipendpoint(addr[0], port);
tcpc.connect(ep);

// 获得流对象
stream s = tcpc.getstream();
byte[] b = encoding.ascii.getbytes(remotefilename.tochararray());
s.write( b, 0, b.length );
int bytes;
filestream fs = new filestream(localfilename, filemode.openorcreate);
binarywriter w = new binarywriter(fs);
// 读取流对象,并将其转换为ascii码
while( (bytes = s.read(read, 0, read.length)) != 0)
{
w.write(read, 0, bytes);
read = new byte[1024];
}
tcpc.close();
w.close();
fs.close();
}
catch(exception ex)
{
throw new exception(ex.tostring());
}
}
}
}

posted on 2011-12-15 13:34  注销账户  阅读(195)  评论(0)    收藏  举报

导航