代码中的log.h log.c比较简单
void logcmd() 记录命令 int logfile();运行日志的记录
int init_logfile() 开启log文件
源码比较清晰也很简单。 可以直接看代码
//=====================================================================================
peer代码中 我们先来看看结构体
1 typedef struct _Request_piece { 2 int index; // 请求的piece的索引 也是bitmap中的index?? 3 int begin; // 请求的piece的偏移 4 int length; // 请求的长度,一般为16KB 5 struct _Request_piece *next; 6 } Request_piece;
1 typedef struct _Peer { 2 int socket; // 通过该socket与peer进行通信 3 char ip[16]; // peer的ip地址 4 unsigned short port; // peer的端口号 5 char id[21]; // peer的id 6 7 int state; // 当前所处的状态 8 9 int am_choking; // 是否将peer阻塞 10 int am_interested; // 是否对peer感兴趣 11 int peer_choking; // 是否被peer阻塞 12 int peer_interested; // 是否被peer感兴趣 13 14 Bitmap bitmap; // 存放peer的位图 15 16 char *in_buff; // 存放从peer处获取的消息 17 int buff_len; // 缓存区in_buff的长度 18 char *out_msg; // 存放将发送给peer的消息 19 int msg_len; // 缓冲区out_msg的长度 20 char *out_msg_copy; // out_msg的副本,发送时使用该缓冲区 21 int msg_copy_len; // 缓冲区out_msg_copy的长度 22 int msg_copy_index; // 下一次要发送的数据的偏移量 23 24 Request_piece *Request_piece_head; // 向peer请求数据的队列 25 Request_piece *Requested_piece_head; // 被peer请求数据的队列 26 27 unsigned int down_total; // 从该peer下载的数据的总和 28 unsigned int up_total; // 向该peer上传的数据的总和 29 30 time_t start_timestamp; // 最近一次接收到peer消息的时间 31 time_t recet_timestamp; // 最近一次发送消息给peer的时间 32 33 time_t last_down_timestamp; // 最近下载数据的开始时间 34 time_t last_up_timestamp; // 最近上传数据的开始时间 35 long long down_count; // 本计时周期从peer下载的数据的字节数 36 long long up_count; // 本计时周期向peer上传的数据的字节数 37 float down_rate; // 本计时周期从peer处下载数据的速度 38 float up_rate; // 本计时周期向peer处上传数据的速度 39 40 struct _Peer *next; // 指向下一个Peer结构体 41 } Peer;
注释标注的很清晰。 注意一点的是Peer和 Request_piece都是链表形式
Peer结构体体中 int state; // 当前所处的状态
状态定义为以下几种
#define INITIAL -1 // 表明处于初始化状态
#define HALFSHAKED 0 // 表明处于半握手状态
#define HANDSHAKED 1 // 表明处于全握手状态
#define SENDBITFIELD 2 // 表明处于已发送位图状态
#define RECVBITFIELD 3 // 表明处于已接收位图状态
#define DATA 4 // 表明处于与peer交换数据的状态
#define CLOSING 5 // 表明处于即将与peer断开的状态
但是状态的切换是不在Peer.c这个代码中, 真正的代码切换是在流程处理中,后面其他代码会慢慢讲到
先来看看Peer的初始化
1 int initialize_peer(Peer *peer) 2 { 3 if(peer == NULL) return -1; 4 5 peer->socket = -1; 6 memset(peer->ip,0,16); 7 peer->port = 0; 8 memset(peer->id,0,21); 9 peer->state = INITIAL; 10 11 peer->in_buff = NULL; 12 peer->out_msg = NULL; 13 peer->out_msg_copy = NULL; 14 15 peer->in_buff = (char *)malloc(MSG_SIZE); 16 if(peer->in_buff == NULL) goto OUT; 17 memset(peer->in_buff,0,MSG_SIZE); 18 peer->buff_len = 0; 19 20 peer->out_msg = (char *)malloc(MSG_SIZE); 21 if(peer->out_msg == NULL) goto OUT; 22 memset(peer->out_msg,0,MSG_SIZE); 23 peer->msg_len = 0; 24 25 peer->out_msg_copy = (char *)malloc(MSG_SIZE); 26 if(peer->out_msg_copy == NULL) goto OUT; 27 memset(peer->out_msg_copy,0,MSG_SIZE); 28 peer->msg_copy_len = 0; 29 peer->msg_copy_index = 0; 30 31 peer->am_choking = 1; 32 peer->am_interested = 0; 33 peer->peer_choking = 1; 34 peer->peer_interested = 0; 35 36 peer->bitmap.bitfield = NULL; 37 peer->bitmap.bitfield_length = 0; 38 peer->bitmap.valid_length = 0; 39 40 peer->Request_piece_head = NULL; 41 peer->Requested_piece_head = NULL; 42 43 peer->down_total = 0; 44 peer->up_total = 0; 45 46 peer->start_timestamp = 0; 47 peer->recet_timestamp = 0; 48 49 peer->last_down_timestamp = 0; 50 peer->last_up_timestamp = 0; 51 peer->down_count = 0; 52 peer->up_count = 0; 53 peer->down_rate = 0.0; 54 peer->up_rate = 0.0; 55 56 peer->next = (Peer *)0; 57 return 0; 58 59 OUT: 60 if(peer->in_buff != NULL) free(peer->in_buff); 61 if(peer->out_msg != NULL) free(peer->out_msg); 62 if(peer->out_msg_copy != NULL) free(peer->out_msg_copy); 63 return -1; 64 }
该创建的创建 该分配的分配 该置零的置零
这里使用了不常见的GOTO。为了保证逻辑清晰,一般是不允许代码里四处GOTO跳转的。
但是GOTO在跳出多重循环和 调至结尾释放资源是比较清晰简洁的写法。
GOTO可以避免多处return忘记释放资源,而是跳转到结尾释放资源后return。return值在处理流程中会赋值1或者-1 表示成功与否
这种写法在结构复杂,多出return还有资源要释放时可以尝试使用下.
其他函数比较简单
Peer* add_peer_node(); // 添加一个peer结点 插入链表
int del_peer_node(Peer *peer); // 从链表中删除一个peer结点
void free_peer_node(Peer *node); // 释放一个peer的内存
int cancel_request_list(Peer *node); // 撤消当前请求队列
int cancel_requested_list(Peer *node); // 撤消当前被请求队列
void release_memory_in_peer(); // 释放peer.c中的动态分配的内存
void print_peers_data(); // 打印peer链表中某些成员的值,用于调试
1 Peer* add_peer_node() 2 { 3 int ret; 4 Peer *node, *p; 5 6 // 分配内存空间 7 node = (Peer *)malloc(sizeof(Peer)); 8 if(node == NULL) { 9 printf("%s:%d error ",__FILE__,__LINE__); 10 return NULL; 11 } 12 13 // 进行初始化 14 ret = initialize_peer(node); 15 if(ret < 0) { 16 printf("%s:%d error ",__FILE__,__LINE__); 17 free(node); 18 return NULL; 19 } 20 21 // 将node加入到peer链表中 22 if(peer_head == NULL) { peer_head = node; } 23 else { 24 p = peer_head; 25 while(p->next != NULL) p = p->next; 26 p->next = node; 27 } 28 29 return node; 30 } 31 32 int del_peer_node(Peer *peer) 33 { 34 Peer *p = peer_head, *q; 35 36 if(peer == NULL) return -1; 37 38 while(p != NULL) { 39 if( p == peer ) { 40 if(p == peer_head) peer_head = p->next; 41 else q->next = p->next; 42 free_peer_node(p); // 可能存在问题 43 return 0; 44 } else { 45 q = p; 46 p = p->next; 47 } 48 } 49 50 return -1; 51 } 52 53 // 撤消当前请求队列 54 int cancel_request_list(Peer *node) 55 { 56 Request_piece *p; 57 58 p = node->Request_piece_head; 59 while(p != NULL) { 60 node->Request_piece_head = node->Request_piece_head->next; 61 free(p); 62 p = node->Request_piece_head; 63 } 64 65 return 0; 66 } 67 68 // 撤消当前被请求队列 69 int cancel_requested_list(Peer *node) 70 { 71 Request_piece *p; 72 73 p = node->Requested_piece_head; 74 while(p != NULL) { 75 node->Requested_piece_head = node->Requested_piece_head->next; 76 free(p); 77 p = node->Requested_piece_head; 78 } 79 80 return 0; 81 } 82 83 void free_peer_node(Peer *node) 84 { 85 if(node == NULL) return; 86 if(node->bitmap.bitfield != NULL) { 87 free(node->bitmap.bitfield); 88 node->bitmap.bitfield = NULL; 89 } 90 if(node->in_buff != NULL) { 91 free(node->in_buff); 92 node->in_buff = NULL; 93 } 94 if(node->out_msg != NULL) { 95 free(node->out_msg); 96 node->out_msg = NULL; 97 } 98 if(node->out_msg_copy != NULL) { 99 free(node->out_msg_copy); 100 node->out_msg_copy = NULL; 101 } 102 103 cancel_request_list(node); 104 cancel_requested_list(node); 105 106 // 释放完peer成员的内存后,再释放peer所占的内存 107 free(node); 108 } 109 110 void release_memory_in_peer() 111 { 112 Peer *p; 113 114 if(peer_head == NULL) return; 115 116 p = peer_head; 117 while(p != NULL) { 118 peer_head = peer_head->next; 119 free_peer_node(p); 120 p = peer_head; 121 } 122 } 123 124 void print_peers_data() 125 { 126 Peer *p = peer_head; 127 int index = 0; 128 129 while(p != NULL) { 130 printf("peer: %d down_rate: %.2f ", index, p->down_rate); 131 132 index++; 133 p = p->next; 134 } 135 }
都是常规链表操作
//=======================================================================
参考
《linux c编程实战》第十三章节btcorrent 及代码