📄 policy.c
字号:
p->up_rate = 0.0f;
p->up_count = 0;
} else {
t = time_now - p->last_up_timestamp;
if(t == 0) printf("%s:%d time is 0\n",__FILE__,__LINE__);
else p->up_rate = p->up_count / t;
p->up_count = 0;
p->last_up_timestamp = 0;
}
p = p->next;
}
return 0;
}
// 计算总的下载和上传速度
int compute_total_rate()
{
Peer *p = peer_head;
total_peers = 0;
total_down = 0;
total_up = 0;
total_down_rate = 0.0f;
total_up_rate = 0.0f;
while(p != NULL) {
total_down += p->down_total;
total_up += p->up_total;
total_down_rate += p->down_rate;
total_up_rate += p->up_rate;
total_peers++;
p = p->next;
}
return 0;
}
int is_seed(Peer *node)
{
int i;
unsigned char c = (unsigned char)0xFF, last_byte;
unsigned char cnst[8] = { 255, 254, 252, 248, 240, 224, 192, 128 };
if(node->bitmap.bitfield == NULL) return 0;
for(i = 0; i < node->bitmap.bitfield_length-1; i++) {
if( (node->bitmap.bitfield)[i] != c ) return 0;
}
// 获取位图的最后一个字节
last_byte = node->bitmap.bitfield[i];
// 获取最后一个字节的无效位数
i = 8 * node->bitmap.bitfield_length - node->bitmap.valid_length;
// 判断最后一个是否位种子的最后一个字节
if(last_byte >= cnst[i]) return 1;
else return 0;
}
// 生成request请求消息,实现了片断选择算法,17为一个request消息的固定长度
int create_req_slice_msg(Peer *node)
{
int index, begin, length = 16*1024;
int i, count = 0;
if(node == NULL) return -1;
// 如果被peer阻塞或对peer不感兴趣,就没有必要生成request消息
if(node->peer_choking==1 || node->am_interested==0 ) return -1;
// 如果之前向该peer发送过请求,则根据之前的请求构造新请求
// 遵守一条原则:同一个piece的所有slice应该从同一个peer处下载
Request_piece *p = node->Request_piece_head, *q = NULL;
if(p != NULL) {
while(p->next != NULL) { p = p->next; } // 定位到最后一个结点处
// 一个piece的最后一个slice的起始下标
int last_begin = piece_length - 16*1024;
// 如果是最后一个piece
if(p->index == last_piece_index) {
last_begin = (last_piece_count - 1) * 16 * 1024;
}
// 当前piece还有未请求的slice,则构造请求消息
if(p->begin < last_begin) {
index = p->index;
begin = p->begin + 16*1024;
count = 0;
while(begin!=piece_length && count<1) {
// 如果是最后一个piece的最后一个slice
if(p->index == last_piece_index) {
if( begin == (last_piece_count - 1) * 16 * 1024 )
length = last_slice_len;
}
create_request_msg(index,begin,length,node);
q = (Request_piece *)malloc(sizeof(Request_piece));
if(q == NULL) {
printf("%s:%d error\n",__FILE__,__LINE__);
return -1;
}
q->index = index;
q->begin = begin;
q->length = length;
q->next = NULL;
p->next = q;
p = q;
begin += 16*1024;
count++;
}
return 0; // 构造完毕,就返回
}
}
// 然后去btcache_head中寻找这样的piece:它没有下载完,但它不在任何peer的
// request消息队列中,应该优先下载这样的piece,出现这样的piece的原因是:
// 从一个peer处下载一个piece,还没下载完,那个peer就将我们choke了或下线了
// 但是测试结果表明, 以这种方式这种方式创建rquest请求执行效率并不高
// 如果直接丢弃未下载完成的piece,则没有必要进行这种生成请求的方式
// int ret = create_req_slice_msg_from_btcache(node);
// if(ret == 0) return 0;
// 生成随机数
if(get_rand_numbers(pieces_length/20) == -1) {
printf("%s:%d error\n",__FILE__,__LINE__);
return -1;
}
// 随机选择一个piece的下标,该下标所代表的piece应该没有向任何peer请求过
for(i = 0; i < pieces_length/20; i++) {
index = rand_num[i];
// 判断对于以index为下标的piece,peer是否拥有
if( get_bit_value(&(node->bitmap),index) != 1) continue;
// 判断对于以index为下标的piece,是否已经下载
if( get_bit_value(bitmap,index) == 1) continue;
// 判断对于以index为下标的piece,是否已经请求过了
Peer *peer_ptr = peer_head;
Request_piece *reqt_ptr;
int find = 0;
while(peer_ptr != NULL) {
reqt_ptr = peer_ptr->Request_piece_head;
while(reqt_ptr != NULL) {
if(reqt_ptr->index == index) { find = 1; break; }
reqt_ptr = reqt_ptr->next;
}
if(find == 1) break;
peer_ptr = peer_ptr->next;
}
if(find == 1) continue;
break; // 程序若执行到此处,说明已经找到一个复合要求的index
}
if(i == pieces_length/20) {
if(end_mode == 0) end_mode = 1;
for(i = 0; i < pieces_length/20; i++) {
if( get_bit_value(bitmap,i) == 0 ) { index = i; break; }
}
if(i == pieces_length/20) {
printf("Can not find an index to IP:%s\n",node->ip);
return -1;
}
}
// 构造piece请求消息
begin = 0;
count = 0;
p = node->Request_piece_head;
if(p != NULL)
while(p->next != NULL) p = p->next;
while(count < 4) {
// 如果是构造最后一个piece的请求消息
if(index == last_piece_index) {
if(count+1 > last_piece_count)
break;
if(begin == (last_piece_count - 1) * 16 * 1024)
length = last_slice_len;
}
create_request_msg(index,begin,length,node);
q = (Request_piece *)malloc(sizeof(Request_piece));
if(q == NULL) { printf("%s:%d error\n",__FILE__,__LINE__); return -1; }
q->index = index;
q->begin = begin;
q->length = length;
q->next = NULL;
if(node->Request_piece_head == NULL) { node->Request_piece_head = q; p = q; }
else { p->next = q; p = q; }
//printf("*** create request index:%-6d begin:%-6x to IP:%s ***\n",
// index,q->begin,node->ip);
begin += 16*1024;
count++;
}
if(rand_num != NULL) { free(rand_num); rand_num = NULL; }
return 0;
}
// 以下这个函数实际并未调用,若要使用需先在头文件中声明
int create_req_slice_msg_from_btcache(Peer *node)
{
// 指针b用于遍历btcache缓冲区
// 指针b_piece_first指向每个piece第一个slice处
// slice_count指明一个piece含有多少个slice
// valid_count指明一个piece中已下载的slice数
Btcache *b = btcache_head, *b_piece_first;
Peer *p;
Request_piece *r;
int slice_count = piece_length / (16*1024);
int count = 0, num, valid_count;
int index = -1, length = 16*1024;
while(b != NULL) {
if(count%slice_count == 0) {
num = slice_count;
b_piece_first = b;
valid_count = 0;
index = -1;
// 遍历btcache中一个piece的所有slice
while(num>0 && b!=NULL) {
if(b->in_use==1 && b->read_write==1 && b->is_writed==0)
valid_count++;
if(index==-1 && b->index!=-1) index = b->index;
num--;
count++;
b = b->next;
}
// 找到一个未下载完piece
if(valid_count>0 && valid_count<slice_count) {
// 检查该piece是否存在于某个peer的请求队列中
p = peer_head;
while(p != NULL) {
r = p->Request_piece_head;
while(r != NULL) {
if(r->index==index && index!=-1) break;
r = r->next;
}
if(r != NULL) break;
p = p->next;
}
// 如果该piece没有存在于任何peer的请求队列中,那么就找到了需要的piece
if(p==NULL && get_bit_value(&(node->bitmap),index)==1) {
int request_count = 5;
num = 0;
// 将r定位到peer最后一个请求消息处
r = node->Request_piece_head;
if(r != NULL) {
while(r->next != NULL) r = r->next;
}
while(num<slice_count && request_count>0) {
if(b_piece_first->in_use == 0) {
create_request_msg(index,num*length,length,node);
Request_piece *q;
q = (Request_piece *)malloc(sizeof(Request_piece));
if(q == NULL) {
printf("%s:%d error\n",__FILE__,__LINE__);
return -1;
}
q->index = index;
q->begin = num*length;
q->length = length;
q->next = NULL;
printf("create request from btcache index:%-6d begin:%-6x\n",
index,q->begin);
if(r == NULL) {
node->Request_piece_head = q;
r = q;
} else{
r->next = q;
r = q;
}
request_count--;
}
num++;
b_piece_first = b_piece_first->next;
}
return 0;
}
}
}
}
return -1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -