种子解析模块设计与实现

解析文件主要在parse_metafile.h和parse_metafile.c中实现。
//parse_metafile.h 解析文件
#ifndef PARSE_METAFILE
#define PARSE_METAFILE//保存种子文件中获取的tracker的URL
typedef struct _Announce_list
{char announce[128];struct _Announce_list *next;
} Announce_list;//保存各个待下载的文件的路径长度
typedef struct _Files
{char path[256];long length;struct _Files *next;
} Files;int read_metafile(char *metafile_name);         //读取种子文件
int find_keyword(char *keyword, long *position);//在种子文件中查找关键字
int read_announce_list();               //获取各个tracker服务器的地址
int add_an_announce(char *url);     //向tracker列表添加一个urlint get_piece_length();  //获取每个piece的长度,一般为256KB
int get_pieces();       //获得各个piece的hash值int is_multi_files();  //判断下载的是单个还是多个文件
int get_file_name();    //获取文件名,对于多文件获取的目录名
int get_file_length();  //获取待下载的文件总长度
int get_files_length_path();//获取文件的路径和长度,对多文件种子有效int get_info_hash();    //由info关键词对应的值计算info_hash
int get_peer_id();      //生成peer_id,每个peer都有一20字节的peer_idvoid release_memory_in_parse_metafile();   //释放parse_metafile.c中动态分配的内存
int parse_metafile(char *metafile); //调用本文件中定义的函数,完成解析种子文件#endif

以下是parse_metafile.c文件的头部

//parse_metafile.c  解析文件
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "parse_metafile.h"
#include "shal.h"char *metafile_content = NULL;  //保存种子的内容
long filesize;                  //种子的长度int piece_length = 0;       //每个piece的长度一般为256KB
char *pieces = NULL;       //保存每个pieces的hash值,每个为20B
int pieces_length = 0;     //缓冲区pieces的长度int multi_file = 0;      //指明是单文件还是多文件
char *file_name = NULL;    //对于单文件,存放文件;对于多文件,存放目录名
long long file_length = 0; //存放待下载的文件的总长度
Files *files_head = NULL;  //对多文件种子有效,存放各个文件的路径和长度
unsigned char info_hash[20];    //保存info_hash的值,连接tracker和peer时使用
unsigned char peer_id[20];  //保存peer_id的值,连接peer时使用Announce_list *announce_list_head = NULL;    //用于保存所有trackr的服务器的URL

具体函数如下:

int read_metafile(char *metafile_name),此函数的说明在代码中不再另写。
/*
* int read_metafile(char *metafile_name)
*解析种子文件
*metafile_name是种子文件名
*处理成功返回0,否则返回-1
*将种子文件的内容读入到全局变量metafile_content所指的缓存区中*说明 编译器预定义的宏__FILE__和__LINE__在程序中可以直接使用。
*__FILE__代表该宏所在源文件的文件名,在源文件parse_metafile.c中
*该宏的值等于"parse_metafile.c",宏__LINE__的值为__LINE__所在的行
*号
*
*
*/
int read_metafile(char *metafile_name)
{long i;//以二进制、只读的方式打开文件FILE *fp = fopen(metafile_name, "rb");if(fp == NULL){printf("%s:%d can not open file\n", __FILE__, __LINE__);return -1;}//获得种子文件的长度,fieszie为全局变量,在parse_metafile_namefseek(fp , 0, SEEK_END);filesize = ftell(fp);if(fileszie == -1){printf("%s:%d fseek failed\n", __FILE__,__LINE__);return -1;}metafile_content = (char *)malloc(filesize+1);if(metafile_content == NULL){printf("%s:%d malloc failed\n", __FILE__,__LINE__);return -1;}//读取种子文件的内容到metafile_content缓冲区中fseek(fp, 0, SEEK_SET);for(i = 0; i < filesize; i++){metafile_content[i] = fgetc(fp);}metafile_content[i] = '\0';fclose(fp);#ifdef DEBUGprintf("metafile size is: &ld\n", filesize);
#endifreturn 0;
}

int find_keyword(char *keyword,long *position)

/*
int find_keyword(char *keyword, long *position)
功能:从种子文件中查找某个关键字
参数:keyword为要查找的关键字,position用于返回关键字第一个字符所在的下标.
返回:成功找到关键字返回1,未找到返回0,执行失败返回-1
*/
int find_keyword(char *keyword, long *position)
{long i;*position = -1;if(keyword == NULL)return 0;for(i = 0; i < filesize - strlen(keyword); i++){if( memcmp(&metafile_content[i], keyword, strlen(keyword))==0){*position = i;return 1;}}return 0;
}

函数说明:此函数用于查找某个关键字(B编码的关键字)。例如:“8:announce”和“13:announce-list”之后是Tracker服务器的地址(URL),找到该关键字后,可以获取Tracker的地址。

int read_announce_list()
/*
功能:获得Tracker地址,并将获得的地址保存到全局变量announce_list_head指向的List中
*/
int read_announce_list()
{Announce_list *node = NULL;Announce_list *p = NULL;int len = 0;long i;if( find_keyword("13:announce-list", &i) == 0){//无"13:announce-list"关键字if( find_keyword("8:announce", &i) == 1){//跳过"8:announce"i = i + strlen("8:announce"); //i未加前是字符串的起始位置//检测字符串后边的字符是否是阿拉伯数字//获取URL的长度while(isdigit(metafile_content[i])){len = len * 10 + (metafile_content[i] - '0');i++;}i++; //跳过':'//申请堆空间保存Tracker的URLnode = (Announce_list *)malloc(sizeof(Announce_list));strcpy(node->announce, &metafile_content[i], len);node->announce[len] = '\0';node->next = NULL;announce_list_head = node;}}else{/*如果有13:announce-list关键字不用处理8:announce关键词**使用备用的URL(备用URL中包含关键字"8:announce"包含的URL)**关键字"13:announce-list"之后的第一个字符为列表的起始字符'l'**该列表中含有两个元素,这两个元素的类型也都是列表***/i = i + strlen("13:announce-list");i++;  //跳过'1'while(metafile_content[i] != 'e'){i++;   //跳过'l'/**检查输入的参数是否为阿拉伯数字*获取URL的长度*/while(isdigit(metafile_content[i])){len = len * 10 + (metafile_content[i] - '0');i++;}if(metafile_content[i] == ':')i++;   //跳过':'elsereturn -1;//只处理以http开头的tracker地址,不处理以udp开头的地址if(memcmp(&metafile_content[i], "http", 4) == 0){node = (Announce_list *)malloc(sizeof(Announce_list));strcpy(node->announce, &metafile_content[i],len);node->announce[len] = '\0';node->next = NULL;if(announce_list_head == NULL){announce_list_head = node;}else{p = announce_list_head;while(p->next != NULL)p = p->next;    //使p指针指向最后个节点p->next = node;    //node成为tracker列表的最后一个节点}}i = i + len;len = 0;i++; //跳过'e'if(i >= filesize)return -1;}   //while循环结束}
#ifdef DEBUGp = announce_list_head;while(p != NULL){printf("%s\n", p->announce);p = p->next;}
#endifreturn 0;
}

某种子文件的开头部分如下,可以帮助理解我的注释:

d8:announce32:http://tk.greedland.net/announce13:announce-listl132:http://tk.greedland.net/announcee113:http://th2.greedland.net/announceee...

第一个字符'd'是B编码中字典的起始符,接着是关键字“8:announce”,该关键字是长度为8的字符串,其对应的值为长度为32的字符串"32:http://tk.greedland,net/announce"是一个Tracker服务器地址(URL),接着是关键字"13:annunce-list",该关键字对应的是一个列表,应为关键字"13:announce-list"之后是第一个字符的起始字符"l",该列表中还有这两个元素的类型也都是列表。

如果有关键字"13:announce-list"哪吗就不用处理关键字"8:announce"的原因在于,前者对应的值必定包含对应的后者的值。

...

Linux BT下载(7)-种子解析模块设计与实现1相关推荐

  1. Linux BT下载(1)-基础入门

    什么是BT软件 很多人用过比特彗星.迅雷下载,PPLive等软件它们都采用了BT协议,故可以称为BT软件. 什么是BT协议 2003年,软件工程师Bram Cohen发明了BitTorrent协议,即 ...

  2. BT下载 BitComet

    这两天为了下VISTA,弄了BT下载,传说中这玩意神奇,这两天果然让我见识了..是挺爽,但是就是条件太多. 我是上海市有线通网络,1M的带宽.平时HTTP,FTP下载最大速度在120K/S.感觉一般. ...

  3. python下载bt文件_bittorrent 种子文件结构解析

    原文链接:http://luoguochun.cn/2014/09/17/bt-file-structure/ 原文作者:buf1024 估计 80% 以上接触互联网的人都知道 bt 是什么东西,任何 ...

  4. 用python实现bt下载_Python边学边用--BT客户端实现之(一)BitTorrent文件解析

    原博文 2012-09-29 23:17 − BitTorrent文件解析: BitTorrent文件使用bencode编码,其中包括了4种数据类型: 'd' 开头表示是dict类型,'e'表示结束 ...

  5. 强力推荐Linux下的五大BT下载工具

    强力推荐Linux下的五大BT下载工具 2009年03月11日01:22 来源:NULL 作者:NULL 编辑:周荣茂 评论:0条 本文Tag: linux Linux新闻 在Windows操作系统中 ...

  6. Linux下最好用的五大BT下载工具

    1.qBitTorrent qBitTorrent是Ubuntu Linux中最受欢迎的P2P软件之一.出自一名法国大学生之手的qBitTorrent功能强大,界面精美,操作直观. qBitTorre ...

  7. BT下载教程之UPnP功能使用、BT端口映射、内网外网之完全解析

    以下是微软官方网站对UPnP的解释: 问:什么是 UpnP? 答:通用即插即用 (UPnP) 是一种用于 PC 机和智能设备(或仪器)的常见对等网络连接的体系结构,尤其是在家庭中.UPnP 以 Int ...

  8. transmission Linux(debian)下的BT下载客户端安装

    transmission Linux(debian)下的BT下载客户端安装 转载于:https://blog.51cto.com/2042617/1597540

  9. linux 安装bt下载软件,centos6.3安装linux下的BT软件qbittorrent的方法

    原创内容,转载请注明出处:https://www.myzhenai.com/thread-15430-1-1.html https://www.myzhenai.com.cn/post/942.htm ...

  10. 镇江php开发,myweb 我的家乡镇江,web技术开发的网站,三层架构,5大模块设计 WEB(ASP,PHP,...) 238万源代码下载- www.pudn.com...

    文件名称: myweb下载 收藏√  [ 5  4  3  2  1 ] 开发工具: HTML 文件大小: 8226 KB 上传时间: 2015-04-11 下载次数: 0 提 供 者: min 详细 ...

最新文章

  1. 基于双目视觉的目标检测与追踪方案详解
  2. java多线程中方法_java中多线程 - 多线程中的基本方法
  3. 产品微操的艺术:提高核心指标的5个需求原理(1~5完)
  4. 14种东西帮你治疗口腔溃疡 - 生活至上,美容至尚!
  5. java中上传文件_Java中文件上传下载 --使用Minio
  6. Spring Boot——读取.properties配置文件解决方案
  7. android 截图 listview,Android屏幕及view的截图实例详解
  8. i红枣 建议:程序员要多吃点红枣
  9. 基于JAVA+SpringMVC+Mybatis+MYSQL的记账管理系统
  10. python中有readall吗_在python中使用tn.read_all()读取数据
  11. nekohtml和htmlparser
  12. 黑科技 | 电脑必备黑科技软件
  13. 游戏修改器制作教程五:OllyDBG和其他调试工具
  14. java jdom_java中JDOM的基本使用方法
  15. CRMEB小程序商城v4.0二次开发对接集成阿里云短信
  16. 文献管理软件Mendeley优缺点分析
  17. 通过三点用Java求三角形周长和面积
  18. 巧妙的通过二维码在手机和电脑传递小量数据
  19. oracle 天转换成月函数_oracle日期函数,转换函数
  20. Unity导入fbx模型贴图不显示的问题

热门文章

  1. 二级c语言编程题库100题,计算机二级C语言编程题库100题(70页)-原创力文档
  2. educoder平台答案Java_不会吧!不会还有人没有《java程序设计》学堂在线答案吧...
  3. Java+SSM+Jsp+Mysql项目大学生健康管理系统
  4. iPhoneXR苹果手机中文电路原理图纸
  5. 数据库课程设计:医院门诊管理系统ER图、数据流程图
  6. vs2019番茄助手 附安装教程
  7. 非常难得的 CMOS sensor 工作原理的深入技术科普
  8. IntelliJ IDEA安卓开发环境搭建
  9. 移动端Vue3框架demo
  10. linux为mysql创建gpower_实战:在Java Web 项目中使用HBase