与peer交换数据模块的设计和实现
本模块由多个子模块构成,主要负责与已建立连接的peer交换数据。除此之外,还调用“连接Tracker”模块中定义的函数监视各个套接字,以及尝试与新的peer家里TCP连接。
本模块主要由torrent.h和torrent.c组成。
以下是torrent.h的代码:
//torrent.h
#ifndef TORRENT_H
#define TORRENT_H
#include "tracker.h"
// 负责与所有Peer收发数据、交换消息
int download_upload_with_peers();
int print_peer_list(); //打印peer链表中各个peer的IP和端口号
void print_process_info(); //打印下载进度消息
void clear_connect_tracker(); //释放与连接Tracker有关的一些动态存储空间
void clear_connect_peer(); //释放与连接peer有关的一些动态存储空间
void clear_tracker_response();//释放与解析Tracker回应有关的一些动态存储空间
void release_memory_in_torrent();//释放torrent.c中动态申请的存储空间
#endif
以下是torrent.c文件的头部包含代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netdb.h>
#include <errno.h>
#include "torrent.h"
#include "message.h"
#include "tracker.h"
#include "peer.h"
#include "policy.h"
#include "data.h"
#include "bitfield.h"
#include "parse_metafile.h"
// 接收缓冲区中的数据达到threshold时,需要立即进行处理,否则缓冲区可能会溢出
// 18*1024即18K是接收缓冲区的大小,1500是以太网等局域网一个数据包的最大长度
#define threshold (18*1024-1500)
extern Announce_list *announce_list_head; //指向用于保存Tracker服务器的URL的堆空间
extern char *file_name; //对于单文件存放文件名,多文件存放目录名
extern long long file_length; //待下载文件的总长度
extern int piece_length; //每个piece的长度通常为256K
extern char *pieces; //保存每个piece的哈希值
extern int pieces_length; //保存pieces缓存区的长度
extern Peer *peer_head; //指向保存Peer结构体链表的堆空间
extern long long total_down,total_up;
extern float total_down_rate,total_up_rate;
extern int total_peers;//已经建立连接的总的Peer的数量
extern int download_piece_num;//当前已下载piece的数量
extern Peer_addr *peer_addr_head;//指向保存PeerIP地址和端口号的结构体链表堆空间
int *sock = NULL;//指向保存Tracker的socket文件描述符的堆空间
struct sockaddr_in *tracker = NULL;//指向保存Tracker的sockaddr_in结构体的堆空间
int *valid = NULL;//指向保存是否已与Tracker建立有效socket连接标志的堆空间
int tracker_count = 0;//存储获得的Tracker的URL的数量
int response_len = 0;
int response_index = 0;
char *tracker_response = NULL;
*peer_sock = NULL;//指向保存Peer的socket文件描述符的堆空间
struct sockaddr_in *peer_addr = NULL;//指向保存Peer的sockaddr_in结构体的堆空间
int *peer_valid = NULL;//指向保存是否已与Peer建立有效socket连接标志的堆空间
int peer_count = 0;//存储获得的PeerIP和端口的数量
以下是torrent.c文件的函数实现代码:
int download_upload_with_peers()
负责与所有peer收发数据、交换消息。
流程图如下:
/*
*功能:负责与所有Peer收发数据、交换消息
*传入参数:
*传出参数:
*返回值:
*/
int download_upload_with_peers()
{
Peer *p;