bittorrent 学习(二) LOG日志和peer管理连接

 

代码中的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;
View Code
 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;
View Code

注释标注的很清晰。 注意一点的是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 }
View Code

该创建的创建  该分配的分配  该置零的置零

这里使用了不常见的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\n",__FILE__,__LINE__); 
 10         return NULL;
 11     }
 12 
 13     // 进行初始化
 14     ret = initialize_peer(node);
 15     if(ret < 0) { 
 16         printf("%s:%d error\n",__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 \n", index, p->down_rate);
131 
132         index++;
133         p = p->next;
134     }
135 }
View Code

都是常规链表操作

 //=======================================================================

 

参考

《linux c编程实战》第十三章节btcorrent  及代码

posted on 2018-11-01 10:11  itdef  阅读(488)  评论(0编辑  收藏  举报

导航