Linux BT下载(11)-信号处理模块和Peer管理模块

信号处理模块

本模块由signal_hander.h和signal_hander.c两个文件构成。
以下是signal_hander.h的代码:
//	signal_hander.h
#ifndef SIGNAL_HANDER_H
#define SIGNAL_HANDER_H

// 做一些清理工作,如释放动态分配的内存
void do_clear_work();

// 处理一些信号
void process_signal(int signo);

// 设置信号处理函数
int set_signal_hander();

#endif

以下是signal_hander.c的代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include "signal_hander.h"
#include "parse_metafile.h"
#include "data.h"
#include "bitfield.h"
#include "peer.h"
#include "tracker.h"
#include "torrent.h"

extern int  download_piece_num;
extern int  *fds;
extern int  fds_len;
extern Peer *peer_head;

/*
*功能:程序退出时,执行清理工作
*传入参数:
*传成参数:
*返回值:
*
*/
void do_clear_work()
{
	// 关闭所有peer的socket
	Peer *p = peer_head;
	while(p != NULL) 
	{
		if(p->state != CLOSING)  
			close(p->socket);
		p = p->next;
	}

	// 保存位图
	if(download_piece_num > 0) 
	{
		restore_bitmap();
	}

	// 关闭文件描述符
	int i;
	for(i = 0; i < fds_len; i++) 
	{
		close(fds[i]);
	}
	
	// 释放动态分配的内存
	release_memory_in_parse_metafile();
	release_memory_in_bitfield();
	release_memory_in_btcache();
	release_memory_in_peer();
	release_memory_in_torrent();

	exit(0);
}

void process_signal(int signo)
{
	printf("Please wait for clear operations\n");
	do_clear_work();
}
	
/*
*功能:信号处理函数
*传入参数:
*传成参数:
*返回值:
*
*/
int set_signal_hander()
{
	if(signal(SIGPIPE,SIG_IGN) == SIG_ERR) 
	{
		perror("can not catch signal:sigpipe\n");
		return -1;
	}
	
	if(signal(SIGINT,process_signal)  == SIG_ERR) 
	{
		perror("can not catch signal:sigint\n");
		return -1;
	}
	
	if(signal(SIGTERM,process_signal) == SIG_ERR) 
	{
		perror("can not catch signal:sigterm\n");
		return -1;
	}
	
	return 0;
}


Peer管理模块

系统为每一个与之建立TCP连接的Peer构造一个peer结构体。Peer管理模块负责管理由各个结点构成的Peer链表,主要工作是创建结点,添加结点到Peer链表,从Peer链表中删除结点等。
该模块由peer.h和peer.c组成。
以下是peer.h的代码:
// peer.h
#ifndef PEER_H
#define PEER_H

#include <string.h>
#include <time.h>
#include "bitfield.h"

#define  INITIAL             -1  		// 表明处于初始化状态
#define  HALFSHAKED         	0  		// 表明处于半握手状态
#define  HANDSHAKED       		1  		// 表明处于全握手状态
#define  SENDBITFIELD        	2  		// 表明处于已发送位图状态
#define  RECVBITFIELD         3  		// 表明处于已接收位图状态
#define  DATA                 4  		// 表明处于与peer交换数据的状态
#define  CLOSING              5 		 // 表明处于即将与peer断开的状态

// 发送和接收缓冲区的大小,16K可以存放一个slice,2K可以存放其他消息
#define  MSG_SIZE  2*1024+16*1024

typedef struct _Request_piece 
{
	int     index;                // 请求的piece的索引
	int     begin;                // 请求的piece的偏移
	int     length;               // 请求的长度,一般为16KB
	struct _Request_piece *next;
} Request_piece;

typedef struct  _Peer 
{
	int            socket;                // 通过该socket与peer进行通信
	char           ip[16];                // peer的ip地址
	unsigned short port;                  // peer的端口号
	char           id[21];                // peer的id

	int            state;                 // 当前所处的状态

	int            am_choking;            // 是否将peer阻塞
	int            am_interested;         // 是否对peer感兴趣
	int            peer_choking;          // 是否被peer阻塞
	int            peer_interested;       // 是否被peer感兴趣

	Bitmap         bitmap;                // 存放peer的位图
	
	char           *in_buff;              // 存放从peer处获取的消息
	int            buff_len;              // 缓存区in_buff的长度
	char           *out_msg;              // 存放将发送给peer的消息
	int            msg_len;               // 缓冲区out_msg的长度
	char           *out_msg_copy;         // out_msg的副本,发送时使用该缓冲区
	int            msg_copy_len;          // 缓冲区out_msg_copy的长度
	int            msg_copy_index;        // 下一次要发送的数据的偏移量

	Request_piece  *Request_piece_head;   // 向peer请求数据的队列
	Request_piece  *Requested_piece_head; // 被peer请求数据的队列

	unsigned int   down_total;            // 从该peer下载的数据的总和
	unsigned int   up_total;              // 向该peer上传的数据的总和

	time_t         start_timestamp;       // 最近一次接收到peer消息的时间
	time_t         recet_timestamp;       // 最近一次发送消息给peer的时间

	time_t         last_down_timestamp;   // 最近下载数据的开始时间
	time_t         last_up_timestamp;     // 最近上传数据的开始时间
	long long      down_count;            // 本计时周期从peer下载的数据的字节数
	long long      up_count;              // 本计时周期向peer上传的数据的字节数
	float          down_rate;             // 本计时周期从peer处下载数据的速度
	float          up_rate;               // 本计时周期向peer处上传数据的速度

	struct _Peer   *next;                 // 指向下一个Peer结构体
} Peer;

int   initialize_peer(Peer *peer);        // 对peer进行初始化
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链表中某些成员的值,用于调试

#endif
程序说明:(1)Peer结构体是整个程序最重要的数据结构,也是最负责的数据结构。peer.h定义了7中状态,各个状态转换图如下:

Peer结构体中定义两个发送缓冲区out_msg和out_msg_copy,将刚刚生成的消息暂存在out_msg中,调用套接字函数send向peer发送消息时使用out_msg_copy缓冲区。out_msg_copy缓冲区。out_msg_copy缓冲区的大小是18KB,而send函数一次最多发送1500字节,因此要使用msg_copy_index记录下次发送的数据的起始下标。事实上,send函数一次也可以发送超过1500字节的数据,不过若以这种方式发送导致发送数据混乱,具体原因将会解释。
peer.c文件的头部包含代码如下:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "peer.h"
#include "message.h"
#include "bitfield.h"

extern Bitmap *bitmap;

// 指向当前与之进行通信的peer列表

Peer *peer_head = NULL;

peer.c中各个函数的定义如下:

int initialize_peer(Peer *peer)
/*
*功能:出始化Peer结构体
*传入参数:Peer
*传出参数:无
*返回值:
*	-1 失败
*	0 成功
*/
int  initialize_peer(Peer *peer)
{
	if(peer == NULL)   return -1;

	peer->socket = -1;
	memset(peer->ip,0,16);
	peer->port = 0;
	memset(peer->id,0,21);
	peer->state = INITIAL;

	peer->in_buff      = NULL;
	peer->out_msg      = NULL;
	peer->out_msg_copy = NULL;

	peer->in_buff = (char *)malloc(MSG_SIZE);
	if(peer->in_buff == NULL)  goto OUT;
	memset(peer->in_buff,0,MSG_SIZE);
	peer->buff_len = 0;

	peer->out_msg = (char *)malloc(MSG_SIZE);
	if(peer->out_msg == NULL)  goto OUT;
	memset(peer->out_msg,0,MSG_SIZE);
	peer->msg_len  = 0;
	
	peer->out_msg_copy = (char *)malloc(MSG_SIZE);
	if(peer->out_msg_copy == NULL)  goto OUT;
	memset(peer->out_msg_copy,0,MSG_SIZE);
	peer->msg_copy_len   = 0;
	peer->msg_copy_index = 0;

	peer->am_choking      = 1;
	peer->am_interested   = 0;
	peer->peer_choking    = 1;
	peer->peer_interested = 0;
	
	peer->bitmap.bitfield        = NULL;
	peer->bitmap.bitfield_length = 0;
	peer->bitmap.valid_length    = 0;
	
	peer->Request_piece_head     = NULL;
	peer->Requested_piece_head   = NULL;
	
	peer->down_total = 0;
	peer->up_total   = 0;
	
	peer->start_timestamp     = 0;
	peer->recet_timestamp     = 0;
	
	peer->last_down_timestamp = 0;
	peer->last_up_timestamp   = 0;
	peer->down_count          = 0;
	peer->up_count            = 0;
	peer->down_rate           = 0.0;
	peer->up_rate             = 0.0;
	
	peer->next = (Peer *)0;
	return 0;

OUT:
	if(peer->in_buff != NULL)      free(peer->in_buff);
	if(peer->out_msg != NULL)      free(peer->out_msg);
	if(peer->out_msg_copy != NULL) free(peer->out_msg_copy);
	return -1;
}

Peer *add_peer_node()
/*
*功能:向peer链表添加一个结点
*传入参数:无
*传出参数:无
*返回值:
*	NULL 失败
*	地址 成功
*/
Peer* add_peer_node()
{
	int  ret;
	Peer *node, *p;

	// 分配内存空间
	node = (Peer *)malloc(sizeof(Peer));
	if(node == NULL)  { 
		printf("%s:%d error\n",__FILE__,__LINE__); 
		return NULL;
	}

	// 进行初始化
	ret = initialize_peer(node);
	if(ret < 0) { 
		printf("%s:%d error\n",__FILE__,__LINE__);
		free(node);
		return NULL;
	}

	// 将node加入到peer链表中
	if(peer_head == NULL)  { peer_head = node; }
	else {
		p = peer_head;
		while(p->next != NULL)  p = p->next;
		p->next = node;
	}

	return node;
}

int del_peer_node(Peer *peer)
/*
*功能:从peer链表中删除一个结点
*传入参数:无
*传出参数:无
*返回值:
*	-1 失败
*	0 成功
*/
int del_peer_node(Peer *peer)
{
	Peer *p = peer_head, *q;

	if(peer == NULL)  return -1;

	while(p != NULL) {
		if( p == peer ) {
			if(p == peer_head)  peer_head = p->next;
			else  q->next = p->next;
			free_peer_node(p);  // 可能存在问题
			return 0;
		} else {
			q = p;
			p = p->next;
		}
	}

	return -1;
}

int cancel_request_list(Peer *node)
/*
*功能:撤销当前请求队列
*传入参数:无
*传出参数:无
*返回值:
*	0 成功
*/
int cancel_request_list(Peer *node)
{
	Request_piece  *p;

	p = node->Request_piece_head;
	while(p != NULL) {
		node->Request_piece_head = node->Request_piece_head->next;
		free(p);
		p = node->Request_piece_head;
	}

	return 0;
}

int cancel_requested_list(Peer *node)
/*
*功能:撤消当前被请求队列
*传入参数:无
*传出参数:无
*返回值:
*	0 成功
*/
//
int cancel_requested_list(Peer *node)
{
	Request_piece  *p;
	
	p = node->Requested_piece_head;
	while(p != NULL) {
		node->Requested_piece_head = node->Requested_piece_head->next;
		free(p);
		p = node->Requested_piece_head;
	}
	
	return 0;
}

void free_peer_node(Peer *node)
/*
*功能:释放一个peer结点的内存
*传入参数:无
*传出参数:无
*返回值:
*/
void  free_peer_node(Peer *node)
{
	if(node == NULL)  return;
	if(node->bitmap.bitfield != NULL) {
		free(node->bitmap.bitfield);
		node->bitmap.bitfield = NULL;
	}
	if(node->in_buff != NULL) {
		free(node->in_buff); 
		node->in_buff = NULL;
	}
	if(node->out_msg != NULL) {
		free(node->out_msg);
		node->out_msg = NULL;
	}
	if(node->out_msg_copy != NULL) {
		free(node->out_msg_copy);
		node->out_msg_copy = NULL;
	}

	cancel_request_list(node);
	cancel_requested_list(node);

	// 释放完peer成员的内存后,再释放peer所占的内存
	free(node);
}

void release_memory_in_peer()
/*
*功能:释放peer管理模块中动态申请的内存
*传入参数:无
*传出参数:无
*返回值:
*	NULL 
*/
void  release_memory_in_peer()
{
	Peer *p;

	if(peer_head == NULL)  return;

	p = peer_head;
	while(p != NULL) {
		peer_head = peer_head->next;
		free_peer_node(p);
		p = peer_head;
	}
}

void print_peers_data()
/*
*功能:从peer链表中删除一个结点
*传入参数:无
*传出参数:无
*返回值:
*	-1 失败
*	0 成功
*/
void print_peers_data()
{
	Peer *p    = peer_head;
	int  index = 0;

	while(p != NULL) {
		printf("peer: %d  down_rate: %.2f \n", index, p->down_rate);

		index++;
		p = p->next;
	}
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值