您的位置:首页 > 其它

局域网P2P技术实现

2010-06-17 10:54 218 查看
P2P技术实现方式有很多,现主要介绍利用socket tcp方式构建P2P环境的方法。

在开始的时候主要参考NBD协议部分的server端程序来实现BT服务端程序。

每个client端都有两个进程来实现P2P功能,一个是客户端的server程序,另一个是客户端的client程序。而BT服务器端只有一个进程,负责资源分配和负载平衡等工作。

下面是服务端程序的注意事项。调试是总发现有“Address already in use”信息出现,加入下面代码可以解决此问题。

/* lose the pesky "Address already in use" error message */
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
perror("setsockopt SO_REUSEADDR");
}
if (setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,&yes,sizeof(int)) == -1) {
perror("setsockopt SO_KEEPALIVE");
}

每一个客户端发起请求时,首先询问服务器端,整个下载的镜像的种子分布状态,之后获得每一个片的种子分布状态。服务器端的server为每一个客户端的请求fork出一个进程。等待客户端下载完成后,报告个服务器端,此片我已经下载完成,并更新BT资源数据。同时可以设计客户端向BT服务器是否可以关机/开机做种等机制。

种子资源数据结构如下:

struct pieces_t{
struct list_head head;
struct pieceinfo_t pieceinfo;
u32 len; //how many clients connect the piece
} __attribute__ ((packed));

struct clientinfo_t {
struct list_head list;
char ipaddr[IPADDRLEN];
char mac[MACADDRLEN]; //MAC address
};
struct pieceinfo_t
{
u32 fid;
u64 offset;

u32 size;
int hash;

};

协议单元的程序例程如下:(客户端报告下载完成)

int download_finish(int sock,u32 fid)
{
struct smc_request request;
struct smc_reply reply;
int error = 0;

request.magic = htonl(SMC_REQUEST_MAGIC);
request.type = htonl(REQ_DOWNLOAD_FINISH);
request.fid = htonl(fid); // 0 means all pieces is downloaded

if(tcp_xmit(TCP_WRITE, sock, (char *)&request, sizeof(request)) <= 0) {
fprintf(stderr,"request_update_finish: failed 1/n");
error=-1;
goto err_out;
}

if(tcp_xmit(TCP_READ, sock, (char *)&reply, sizeof(reply)) <= 0) {
fprintf(stderr,"request_update_finish: failed 2/n");
error=-2;
goto err_out;
}

if(reply.error) {
error=-3;
fprintf(stderr,"request_update_finish: failed 3/n");
goto err_out;
}
DEBUG2("DOWNLOAD fid(%d) Finished/n",fid);
err_out:

return error;
}

同时设计了支持黑名单的功能。即当很多客户机(已经下载完毕)关机的情况下,正在下载的客户机避免一些不必要的连接损耗,提供如果connect时返回无法连接,直接把该ip对应的客户机放入blacklist链表中,下次下载时,如果该机器在blacklist中,可以skip掉。同时定期更新黑名单里面的机器。如果里边的机器已经开机。那么可以从黑名单中解放出来,继续给其他的客户机做种。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: