Site Overlay

Linux C 笔记:BT 项目结构分析

正文

入口函数

入口函数

命令行参数检查

命令行参数检查

设置信号处理的回调函数

设置信号处理的回调函数

set_signal_handler

[Not supported by viewer]

对于 SIGPIPE 直接忽略

[Not supported by viewer]

对于中断信号(SIGINT
和终止信号(SIGTERM
移交给 process_signal 处理

[Not supported by viewer]

解析 torrent 文件

解析 torrent 文件

初始化未阻塞 peers

初始化未阻塞 peers

创建下载文件

创建下载文件

创建位图

创建位图

创建缓冲

创建缓冲

数据传输

数据传输

收尾工作

收尾工作

退出

退出

process_signal 

process_signal <br>

直接进行收尾工作

直接进行收尾工作

信号处理模块

信号处理模块

parse_metafile

[Not supported by viewer]

读取种子文件到内存

<div><span>读取种子文件到内存</span></div>

获取tracker服务器的地址

<div><span>获取tracker服务器的地址</span></div>

判断是否为多文件种子

<div><span>判断是否为多文件种子</span></div>

获取每个piece的长度

<div><span> 获取每个piece的长度</span></div>

读取各个piece的哈希值

<div><span>读取各个piece的哈希值</span></div>

获取要下载的文件名(或者目录名)

<div><span>获取要下载的文件名(或者目录名)</span></div>

(多文件种子)获取各个待下载的文件路径和文件长度

<div><span>(多文件种子)获取各个待下载的文件路径和文件长度</span></div>

获取待下载的文件的总长度

<div><span>获取待下载的文件的总长度</span></div>

获得info_hash

[Not supported by viewer]

生成peer_id

[Not supported by viewer]

种子解析模块

种子解析模块

初始化全局变量unchoke_peers

<div><span>初始化全局变量unchoke_peers</span></div>

create_files

[Not supported by viewer]

获取种子中待下载文件的个数

<div><span>获取种子中待下载文件的个数</span></div>

为每个文件申请描述符

<div>为每个文件申请描述符</div>

多文件

多文件

创建与下载文件大小相等的文件并写入空字符  

[Not supported by viewer]

创建(多级)目录

<div>创建(多级)目录</div>

遍历链表,创建各个所需文件,并写入空字符

<div>遍历链表,创建各个所需文件,并写入空字符</div>

为 bitmap 结构初始化

为 bitmap 结构初始化

create_bitfield

[Not supported by viewer]

全新下载

全新下载

设置位图的各位为0

设置位图的各位为0

读取现有位图

读取现有位图

设定正确的值给download_piece_num

<div><span>设定正确的值给download_piece_num</span></div>

实现了断点续传

实现了断点续传

create_btcache

[Not supported by viewer]

1024(缓冲节点数量)次 for 循环

<div><span>1024(缓冲节点数量)次 for 循环</span></div>

初始化当前缓冲节点

<div>初始化当前缓冲节点</div>

循环

循环

连接该节点与下一个节点

<div>连接该节点与下一个节点</div>

连接该节点与下一个节点

<div>连接该节点与下一个节点</div>

初始化最后一个 piece 的缓存空间和index

<div>初始化最后一个 piece 的缓存空间和index</div>

initialize_btcache_node

<div><span>initialize_btcache_node</span></div>

为节点分配内存

<div>为节点分配内存</div>

为节点的 buff 分配内存

<div>为节点的 buff 分配内存</div>

初始化结构体的其它值

<div>初始化结构体的其它值</div>

文件预备模块

文件预备模块

位图管理模块

位图管理模块

缓冲管理模块

缓冲管理模块

download_upload_with_peers

<div><span>download_upload_with_peers</span></div>

局部变量初始化

局部变量初始化

进入主循环

进入主循环

每隔10秒重新选择非阻塞peer

<div><span>每隔10秒重新选择非阻塞peer</span></div>

每隔30秒重新选择可选非阻塞peer

<div><span>每隔30秒重新选择可选非阻塞peer</span></div>

计算各个peer的下载、上传速度

<div><span>计算各个peer的下载、上传速度</span></div>

选择非阻塞的peer

<div><span>选择非阻塞的peer</span></div>

将那些在过去10秒已断开连接而又处于unchoke队列中的peer清除出unchoke队列

[Not supported by viewer]

将那些在过去10秒上传速度超过20KB/S而下载速度过小的peer强行阻塞

<div><span>将那些在过去10秒上传速度超过20KB/S而下载速度过小的peer强行阻塞</span></div>

从当前所有Peer中选出下载速度最快的四个peer

<div><span>从当前所有Peer中选出下载速度最快的四个peer</span></div>

更新 peer

[Not supported by viewer]

对peer的状态值重新赋值

<div><span>对peer的状态值重新赋值</span></div>

创建choke、unchoke消息

<div><span>创建choke、unchoke消息</span></div>

create_chock_interested_msg

<div><span>create_chock_interested_msg</span></div>

select_optunchoke_peer

<div><span>select_optunchoke_peer</span></div>

每隔5分钟

或当前peer数为0

连接tracker

[Not supported by viewer]

如果要连接新的peer

<div><span>如果要连接新的peer</span></div>

创建套接字,向peer发出连接请求

<div><span>创建套接字,向peer发出连接请求</span></div>

状态更新为连接中

<div>状态更新为连接中</div>

开始连接时间改为现在

开始连接时间改为现在

用 FD_ZERO 初始化(清空)

套接字集合

[Not supported by viewer]

如果状态为连接中

<div>如果状态为连接中</div>

将连接tracker的socket加入到待监视的集合中

<div><span>将连接tracker的socket加入到待监视的集合中</span></div>

如果连接tracker超过10秒,则终止连接tracker

<div><span>如果连接tracker超过10秒,则终止连接tracker</span></div>

否则连接各个 tracker

<div>否则连接各个 <span>tracker</span></div>

如果状态为连接tracker结束

<div>如果状态为连接<span>tracker结束</span></div>

与peer建立连接

<div><span>与peer建立连接</span></div>

clear_connect_tracker

<div><span>clear_connect_tracker</span></div>

清理连接的 tracker 数量为 0

<div>清理连接的 tracker 数量为 0</div>

clear_tracker_response

<div><span>clear_tracker_response</span></div>

设置 response_len 为零

<div>设置 <span>response_len 为零</span></div>

设置 response_index 为零

[Not supported by viewer]

如果peer_addr_head不为空,说明可以建立peer链接
设置 connect_peer = -1

[Not supported by viewer]

否则 connect_tracker =1;

[Not supported by viewer]

将peer的socket成员加入到待监视的集合中

<div><span>将peer的socket成员加入到待监视的集合中</span></div>

遍历 peer 的链表,初始化各个 socket

<div><span>遍历 peer 的链表,初始化各个 socket</span></div>

遍历 peer 的链表,初始化各个 socket

<div><span>遍历 peer 的链表,初始化各个 socket</span></div>

设置 select函数的超时时间

<div>设置 <span>select函数的超时时间</span></div>

对各个读写set 进行 select,等待请求到来

<div>对各个读写set 进行 select,等待请求到来</div>

请求到来,执行prepare_
send_have_msg

[Not supported by viewer]

向所有的peer发送have消息

<div><span>向所有的peer发送have消息</span></div>

遍历各个 peer

遍历各个 peer

如果状态为未关闭,且为rset

<div><span>如果状态为未关闭,且为rset</span></div>

接收消息

[Not supported by viewer]

成功则解析所有的消息

<div><span>成功则解析所有的消息</span></div>

如果状态为未关闭,且为wset

<div><span>如果状态为未关闭,且为wset</span></div>

发送各种消息

<div>发送各种消息</div>

如果正在与tracker服务器相连

<div><span>如果正在与tracker服务器相连</span></div>

对于每个 tracker

<div>对于每个 tracker</div>

如果建立好了套接字,但是还没有连接

<div><span>如果建立好了套接字,但是还没有连接</span></div>

尝试 getsockopt 获取套接字选项

[Not supported by viewer]

如果已经成功建立了连接

<div><span>如果</span><span>已经成功建立了连接</span></div>

构建 tracker服务器的地址链表

构建 <span>tracker服务器的地址链表</span>

向tracker服务器发送请求消息

<div><span>向tracker服务器发送请求消息</span></div>

如果需要状态主机从tracker服务器中得到数据

[Not supported by viewer]

读取并处理数据

<div>读取并处理数据</div>

如果正在与 peer 建立连接

[Not supported by viewer]

遍历各个 peer

<div>遍历各个 peer</div>

getsockopt

[Not supported by viewer]

添加 peer 到 peer 链表

<div>添加 peer 到 peer 链表</div>

对处于CLOSING状态的peer,将其从peer队列中删除

[Not supported by viewer]

下载完毕的检测

下载完毕的检测

数据传输和消息通信模块

数据传输和消息通信模块

致谢

感谢 Sky,July,Aspire 的帮助。否则我难以短时间掌握这样一个大的系统的原理。

发表评论

电子邮件地址不会被公开。 必填项已用*标注