代碼中的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;
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; // 當前所處的狀態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 }
該建立的建立 該分配的分配 該置零的置零
這裏使用了不常見的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 }
都是常規鏈表操做
//=======================================================================
參考
《linux c編程實戰》第十三章節btcorrent 及代碼