bittorrent 學習(二) LOG日誌和peer管理鏈接

 

代碼中的log.h log.c比較簡單node

void logcmd() 記錄命令  int logfile();運行日誌的記錄linux

int init_logfile() 開啓log文件編程

源碼比較清晰也很簡單。 能夠直接看代碼緩存

//=====================================================================================socket

 peer代碼中 咱們先來看看結構體ide

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; // 當前所處的狀態spa

狀態定義爲如下幾種調試

#define INITIAL -1 // 代表處於初始化狀態
#define HALFSHAKED 0 // 代表處於半握手狀態
#define HANDSHAKED 1 // 代表處於全握手狀態
#define SENDBITFIELD 2 // 代表處於已發送位圖狀態
#define RECVBITFIELD 3 // 代表處於已接收位圖狀態
#define DATA 4 // 代表處於與peer交換數據的狀態
#define CLOSING 5 // 代表處於即將與peer斷開的狀態rest

 可是狀態的切換是不在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  及代碼

相關文章
相關標籤/搜索