自学C++一年有余,一直想自己开发个什么东西,终于在今年7月份决定写个BT的客户端吧,恩,说干就干,于是开始了这次痛苦的旅程,越深入到各个细节当中越觉得自己可能完不成这个东西了,故决定开始写Blog激励自己一下,也希望能把一个编程新手遇到的各种困难都记录下来,供他人借鉴,也便于自己日后的查寻. 我这人比较罗嗦,可能整个文档中间会夹杂一些个人感悟,期望哪位不幸读到的朋友谅解. 有对P2P一类软件感兴趣的朋友可以加我qq: 2070341一起聊聊, 自己写东西实在是很孤独.
说干就干,说写就写,先从种子文件开始.
(1): Bencoding格式
这个东西是所有相关资源的来源,所以必须先搞定. 下面简单阐述一下,大概格式,有兴趣的网友可以到http://wiki.theory.org/BitTorrentSpecification 参照标准.
Bencoding采用的是一种字典格式,其中包括四种数据类型,string, int, list和dictionary.其中list和dict都是容器,能包含这四种类型的任意一种,dict的key当然就是string,注意,学过设计模式的朋友想到什么了? 对Composite!
string 4:abcd
int i1234e
list l4:abcdi1234ee 一个装有一个string和一个int的list
dict d3:aaal4:abcdi1234eee 一个装有一条记录的字典,key为aaa,value是个list
下面是一段解析bencoding程序的源码,因为整个bencoding文件就是一个dict,所以最后生成的是个dict,然后再用具体的类来解析这个dict得到相应的内容,请看:
这个是实现:
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/***************************************************************************************************************/
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
StringType::assign(
const
std::vector
<
char
>
&
str)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
clear();
m_str = str;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
StringType::StringType(
const
std::vector
<
char
>
&
str) : TypeBase(STRING_TYPE)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
assign(str);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
StringType::StringType(
const
std::
string
&
str) : TypeBase(STRING_TYPE)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
std::vector<char> vstr(str.begin(), str.end());
assign(vstr);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
StringType
&
StringType::
operator
=
(
const
std::vector
<
char
>
&
str)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
assign(str);
return *this;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
StringType::StringType() : TypeBase(STRING_TYPE), m_str(
0
)
...
{}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
StringType::StringType(
const
StringType
&
other) : TypeBase(STRING_TYPE)
...
{ assign(other.m_str); }
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
StringType
&
StringType::
operator
=
(
const
StringType
&
other)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(this != &other)
assign(other.m_str);
return *this;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/*****************************************************************************************************/
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
IntegerType::IntegerType() : TypeBase(INTEGER_TYPE), m_int(
0
)
...
{}
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
IntegerType
&
IntegerType::
operator
=
(
const
t_u_int64 n)
...
{ m_int = n; return *this; }
IntegerType::IntegerType(
const
IntegerType
&
other) : TypeBase(INTEGER_TYPE)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
m_int = other.m_int;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
IntegerType::IntegerType(t_u_int64 n) : TypeBase(INTEGER_TYPE), m_int(n)
...
{}
IntegerType
&
IntegerType::
operator
=
(
const
IntegerType
&
other)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
if(this != &other)
m_int = other.m_int;
return *this;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/*****************************************************************************************************/
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
ListType::ListType() : TypeBase(LIST_TYPE)
...
{}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
ListType::
~
ListType()
...
{ clear(); }
void
ListType::clear()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
ThisIterator beg = m_list_data.begin();
ThisIterator end = m_list_data.end();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
for(ThisIterator it = beg; it != end; ++it)
delete (*it);
m_list_data.clear();
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
ListType::insert(TypeBase
*
ptype)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
m_list_data.push_back(ptype);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
/**/
/*****************************************************************************************************/
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
TypeBase
*
DictType::get_value(
const
std::
string
&
key)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
C_Iterator beg = m_map_data.begin();
C_Iterator end = m_map_data.end();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for(C_Iterator it = beg; it != end; ++it)...{
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if((it->first->get_str()) == key)...{
return (it->second);
}
}
return NULL;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
bool
DictType::set_value(StringType
*
pstr_bt, TypeBase
*
ptype_bt)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
m_map_data[pstr_bt] = ptype_bt;
return true;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
void
DictType::clear()
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
ThisIterator beg = m_map_data.begin();
ThisIterator end = m_map_data.end();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
for(ThisIterator it = beg; it != end; ++it)...{
delete (it->first);
delete (it->second);
}
}
四种类型都派生自一个TypeBase基类, 故ListType和DictType只需装入一个TypeBase*就OK了,Runtime识别的时候用基类的type()const函数返回的DataType 来识别,我这里并没有给基类提供一个更宽大的接口,没必要.
下面是解码类 BExtractor
class
BExtractor :
private
NonCopyable
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
private:
private:
std::vector<t_byte> bfile;
public:
size_t analyzer(size_t beg_pos, TypeBase *&pbase);//供给read_list和read_dict递归提取类型
size_t read_string(size_t beg_pos, StringType &str_bt);
//从指定位置开始位置(基于0)
//将内容加入到一个ListType中,内部调用analyzer函数, 会导致递归调用
//任何错误都将导致返回 0,直接解析失败
//如无错误,则返回读取的内容长度,
size_t read_int(size_t beg_pos, IntegerType &int_bt);
size_t read_list(size_t beg_pos, ListType &list_bt);
size_t read_dict(size_t beg_pos, DictType &dict_bt);
//根据执行起始位置(此起始位置
size_t locate_key(size_t beg_pos, const std::string &key);
public:
//接受一段元数据作分析 当然是bencoding file, 如果未搜索到第一个d,则返回false;
bool set_content(const std::vector<t_byte> &meta);
size_t get_content(size_t b, size_t e, std::vector<t_byte> &content); //根据执行位置提取一段元数据
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
void clear() ...{ bfile.clear(); }
public:
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
BExtractor()...{};
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
~BExtractor()...{};
}
;
#define
ASSERT_POS(pos) { /*assert(pos < bfile.size())*/ if(pos >= bfile.size()) return 0;}
#define
ERR_CHECK(num) { /*assert(num != 0);*/if(num == 0) return 0; }
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
bool
BExtractor::set_content(
const
std::vector
<
t_byte
>
&
meta)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
std::vector<t_byte>::const_iterator it;
it = std::find(meta.begin(), meta.end(), 'd');
if(it == meta.end()) return false;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
bfile.clear();
bfile.resize(meta.size());
std::copy(it, meta.end(), bfile.begin());
return true;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
size_t BExtractor::get_content(size_t b, size_t len, std::vector
<
t_byte
>
&
content)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
ASSERT_POS(b);
ASSERT_POS(b + len);
content.resize(len);
std::vector<t_byte>::const_iterator beg = bfile.begin() + b;
std::vector<t_byte>::const_iterator end = beg + len;
std::copy(beg, end, content.begin());
return len;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
size_t BExtractor::analyzer(size_t beg_pos, TypeBase
*&
pbase)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
IntegerType *pint = NULL;
StringType *pstr = NULL;
ListType *plist = NULL;
DictType *pdict = NULL;
ASSERT_POS(beg_pos);
size_t idx = beg_pos;
char ch = bfile[idx];
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
switch(ch)...{
case 'i':
pint = new IntegerType();
pbase = pint;
return read_int(idx, *pint);
case 'l':
plist = new ListType();
pbase = plist;
return read_list(idx, *plist);
case 'd':
pdict = new DictType();
pbase = pdict;
return read_dict(idx, *pdict);
default:
pstr = new StringType();
pbase = pstr;
return read_string(idx, *pstr);
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
size_t BExtractor::read_list(size_t beg_pos, ListType
&
list_bt)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
TypeBase *pbase = NULL;
size_t idx = beg_pos + 1; //跳过'l';
ASSERT_POS(idx);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while(bfile[idx] != 'e')...{
size_t i = 0;
i = analyzer(idx, pbase);
ERR_CHECK(i);
idx += i;
ASSERT_POS(idx);
list_bt.insert(pbase);
}
return (idx + 1 - beg_pos);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
size_t BExtractor::read_dict(size_t beg_pos, DictType
&
dict_bt)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
size_t idx = beg_pos + 1; //跳过'd';
ASSERT_POS(idx);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
TypeBase *pbase = NULL;
StringType *pstr = NULL;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while(bfile[idx] != 'e')...{
pstr = new StringType();
size_t i = 0;
i = read_string(idx, *pstr);
ERR_CHECK(i);
idx += i;
ASSERT_POS(idx);
i = analyzer(idx, pbase);
ERR_CHECK(i);
idx += i;
ASSERT_POS(idx);
dict_bt.set_value(pstr, pbase);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return (idx + 1 - beg_pos);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
size_t BExtractor::read_string(size_t beg_pos, StringType
&
str_bt)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
str_bt.clear();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
std::string num; //得到前面的数值 4:abcd的4
size_t idx = beg_pos;
ASSERT_POS(idx);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while(bfile[idx] != ':')...{
num += bfile[idx];
++idx;
ASSERT_POS(idx);
}
++idx; //跳过':';
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
size_t len = atoi(num.c_str());
ASSERT_POS((idx + len));
std::vector<char> str(len);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
for(size_t i = 0; i < len; ++i)
str[i] = bfile[idx + i];
if(str.size() != len) return 0;
str_bt = str;
return (idx + len - beg_pos);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
size_t BExtractor::read_int(size_t beg_pos, IntegerType
&
int_bt)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
size_t idx = beg_pos + 1; //跳过'i'
ASSERT_POS(idx);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if(bfile[idx] == 'e') return 0; //如果中间无数值数据
std::string num;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while(bfile[idx] != 'e')...{
char ch = bfile[idx];
if(!std::isdigit(ch) && ch != '-') return 0;
num += ch;
++idx;
ASSERT_POS(idx);
}
int_bt = atoi(num.c_str());
return (idx - beg_pos + 1);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
size_t BExtractor::locate_key(size_t beg_pos,
const
std::
string
&
key)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
assert(bfile[beg_pos] == 'd');
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
size_t idx = beg_pos + 1; //跳过'd';
ASSERT_POS(idx);
TypeBase *pbase = NULL;
StringType key_bt;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
while(bfile[idx] != 'e')...{
size_t i = 0;
i = read_string(idx, key_bt);
ERR_CHECK(i);
idx += i;
ASSERT_POS(idx);
if(key_bt.get_str() == key)
return idx;
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
i = analyzer(idx, pbase);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(i == 0 || ((idx + i) >= bfile.size()))...{
delete pbase;
return 0;
}
idx += i;
}
delete pbase;
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#undef
ASSERT_POS
#undef
ERR_CHECK
这个类负责抽取Bencoding文件为一个巨型的DictType,当然,也可以根据需要再合适的位置进行相应的操作,例如后期的tracker request时候解码tcp tracker返回的信息,这是后话,暂且不提.大概知道是干什么的就成了.下面是对生成的这个DICT类型的信息提取,使用函数
bool
seed_decoder(
const
std::
string
&
fname, SeedInfo
&
seed_info);
SeedInfo结构为:
struct
FileInfo
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
t_u_int64 length;
std::string md5sum;
std::list<std::string> path;
public:
FileInfo();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
~FileInfo() ...{}
FileInfo(const FileInfo& other);
FileInfo& operator=(const FileInfo &other);
public:
void clear();
}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
struct
SeedInfo
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
bool is_multi_files;
std::vector<t_u_int8> info_hash;
//std::string announce; //tracker服务器的URL(字符串)
std::list<std::string> anounce_list; //备用tracker服务器列表(列表)
t_u_int64 creation_date;
//种子创建的时间,Unix标准时间格式,从1970 1月1日 00:00:00到创建时间的秒数(整数)
std::string comment; //备注(字符串)
std::string created_by; //创建人或创建程序的信息(字符串)
std::string name; //多文件时使用,name:最上层的目录名字(字符串)
t_u_int64 piece_lengh; //每个块的大小,单位字节(整数)
std::vector<char> pieces; //每个块的20个字节的SHA1 Hash的值(二进制格式)
std::string publisher;
std::string publisher_url;
std::list<FileInfo> files; //多文件时使用;
size_t pieces_num;
//utf8扩展
bool is_utf8;
std::string publisher_url_utf8;
std::string publisher_utf8;
std::string name_utf8;
std::string comment_utf8;
private:
void copy(const SeedInfo &other);
public:
SeedInfo();
SeedInfo(const SeedInfo& other);
SeedInfo& operator= (const SeedInfo &other);
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
~SeedInfo() ...{}
void clear();
}
;
这个函数的内部实现相当混乱,我不作过分的叙述了,日后要改的,这里有必要提一下的是 : std::vector<t_u_int8> info_hash; //这个数据成员,
它是由整个Bencoding格式文件的字典中的"Info" 这个key所对应的dict类型的160位sha1 hash值, 这个有必要说一下,不太清楚的请参阅相关资料,这东西最好从bit的角度理解,故此,info_hash这个数据成员的.size()为20, typedef unsigned char t_u_int8;
这个几个类都被我放到了头文件bencoding_type.h头文件中了.由于本人软件的设计能力有限,所以整个架构比较乱,后面写了一个包括网络,异步I/O,完成端口,code page转换等繁杂的辅助类,相互的耦合度的比较大, 这个相对来说还是最独立的,所以有些源码就不贴了,有需要的朋友请加我QQ.
Bencoding解码先说到这,明天有空将贴tracker查寻的源码,我尽量保证每天写一篇笔记以记录自己的工作进度!