libed2k源码导读:(二)Session接口以及实现分析

第二章 Session接口以及实现分析

目录

第二章 Session接口以及实现分析

2.1 获取会话状态

2.2 管理会话中所有的传输任务

2.3 管理点对点连接

2.4 管理alert

2.4.1 alert介绍

2.4.2 当前已定义的alert

2.4.3 在程序中接收和处理alert

2.4.4 其他和alert有关的接口

2.5 在服务器上查找文件

2.5.1 搜索请求的格式约定

2.5.2 创建文件查询对象

2.5.3 发送文件搜索请求


和libtorrent一样,libed2k的功能大部分需要使用session类提供的接口,而session类所有功能的具体实现都是在session_impl类中,session对象通过内部的一个session_impl对象指针向外提供接口。session类共有54个成员函数,大致可以分为几类:

  1. 构造及初始化,session()和init()
  2. 获取session的状态,status()
  3. 管理文件传输任务(通过transfer_handle)的接口
  4. 管理点对点连接(通过peer_connection_handle)的接口
  5. 管理alert的一系列接口
  6. 在服务器上查找文件的接口
  7. P2P本地监听端口有关的接口
  8. session选项设置和获取接口
  9. 设置和获取IP过滤的接口
  10. 上传下载限速的接口
  11. 连接/断开服务器的接口
  12. 暂停/恢复整个session的接口
  13. 分享和取消分享的接口
  14. 端口映射相关的接口
  15. kad(dht)功能相关的接口

 

2.1 获取会话状态

 

session状态保存在session_status,通过session类的session_status session::status()成员函数可以获取。当前版本的session_status中并不完整,大部分成员似乎仅仅是为了和尝试libtorrent兼容而设置。

当前可用的状态信息:

struct LIBED2K_EXPORT session_status

{ 

//... 

int upload_rate; //上传速度 

int download_rate; //下载速度 

size_type total_download; //上传总字节数 

size_type total_upload; //下载总字节数 

int payload_upload_rate; //实际数据(负载)上传速度 

int payload_download_rate; //实际数据(负载)下载速度 

size_type total_payload_download; //实际数据(负载)下载总字节数 

size_type total_payload_upload; //实际数据(负载)上传总字节数 

//... 

int num_peers; 

//点对点连接数 

int up_bandwidth_queue; //上传限速时在限速队列中排队的请求个数 

int down_bandwidth_queue; //下载限速时在限速队列中排队的请求个数 

int up_bandwidth_bytes_queue; //上传限速时在队列中排队的总字节数 

int down_bandwidth_bytes_queue; //下载限速时在队列中排队的总字节数 

//... 

};

接下来,我们尝试在conn中添加一条命令"sess_stat",当程序收到这个指令时会打印以上状态信息。

照旧先连接服务器:conn 176.103.48.36 4184 D:\123

然后添加一个下载任务:download_addlink:ed2k://|file|xxxx.m4|1019979999|880260967C066B3C20ED6BDF3CD45EAA|/

最后,输入sess_stat查看session的状态信息,结果如下图:

 

注:这里和payload_upload有关的值为0,是因为本客户端获取到的是一个lowID(本机是内网IP而且UPNP失败导致无法上传)

 

2.2 管理会话中所有的传输任务

 

transfer对象是文件传输任务的抽象,包括文件下载和文件上传的任务,而transfer_handle是一个类似"对象管理器"的概念,它封装了对transer的一些高级接口,对使用者屏蔽了传输任务的细节。接下来我们来看一下session是怎么管理文件传输任务。

 

session提供了以下接口用于管理文件传输任务:

transfer_handle add_transfer(const add_transfer_params& params); 
void post_transfer(const add_transfer_params& params); 
transfer_handle find_transfer(const md4_hash& hash) const; 
std::vector<transfer_handle> get_transfers() const; 
std::vector<transfer_handle> get_active_transfers() const; 
void remove_transfer(const transfer_handle& h, int options = none);

其中:

  • add_transfer和post_transfer用于添加一个任务,不同在于前者是同步过程而后者是异步过程。
  • find_transfer根据文件md4_hash值从内部列表中查找一个任务。
  • get_transfers返回内部所有的任务列表。
  • get_active_transfers返回处于活动状态的任务列表。
  • remove_transfer将一个任务从任务列表里移除。

添加任务时,session::add_transfer做的事情是:

  1. 检查session的状态,如果session处于abort状态,则报告错误并返回一个空句柄。
  2. 确认任务是否已经在session中,如果已经存在则报告错误并返回一个空句柄。
  3. 以传入的add_transfer_params对象作为参数创建一个transfer对象,并调用它的start方法
  4. 将新创建的transfer对象插入到内部列表。
  5. 发送added_transfer_alert通知。

使用post_transfer方法时,将add_transfer封装为一个函数对象并传递给session的boost::io_service以达到异步执行的目的。add_transfer的参数是一个add_transfer_params,它封装了文件名、文件md4和文件存放路径,transfer对象将根据这些信息从服务器和DHT网络中搜索资源。

session内部存放任务列表的数据结构是一个std::map<md4_hash, boost::shared_ptr<transfer>>类型的map映射。一如该类型定义上的字面意思它的键是文件md4而值是一个transfer对象的智能指针。文件传输任务的添加和删除都是在这个列表上通过md4键进行操作。注:在session_impl类中有个目前尚未用到find_transfer的重载函数,它的参数是一个文件路径,在其内部通过合并add_transfer_params中传递的文件存放路径和文件名得到一个路径,再将它与输入参数对比后返回列表中匹配的值。

 

2.3 管理点对点连接

 

在session类中定义了一下成员函数用于管理点对点连接:

peer_connection_handle add_peer_connection(const net_identifier& np); 
peer_connection_handle find_peer_connection(const net_identifier& np) const; 
peer_connection_handle find_peer_connection(const md4_hash& hash) const;

 

这三个函数分别用于添加和查找一个连接,值得一提的是这三个成员函数在未来优化时可能会被从session类的公开接口中移除。因为从逻辑上说点对点的连接对象应该从属于transfer任务对象而不是从属于整个session,管理连接peer_connection的对象应该是某个具体任务(可能不是transfer任务,以后可能会增加其他需要创建连接的任务类型)。无论如何既然它们现在已经在session中,我们不妨简单看一下它们的实现。

1)add_peer_connection做以下事情:

  • 在内部的连接列表(m_connections)中查找是否连接已经存在
  • 从net_identifier类型的参数中得到需要连接的IP(仅支持IPv4)和端口
  • 在io_service中创建tcp::socket类型的连接,为连接预分配所需的收发缓冲区。
  • 插入到session内部的(connection_queue类型)m_half_open队列中,在合适的时候connection_queue会调用peer_connection::connect方法连接np参数指定的peer。在peer_connection::connect中指定了回调peer_connection::on_connect,在连接成功时它将被调用,然后启动连接任务对应的协议规定的数据收发过程。

2)两个find_peer_connection函数做以下事情:

遍历session内部的连接列表(m_connections),对每一个成员执行peer_connection::has_network_point或peer_connection::has_hash(两个重载函数一个指定的是net_identifer另一个指定的是md4_hash),找到匹配的对象后用transfer_handle封装它然后返回。

 

2.4 管理alert

 

和libtorrent相似,异步过程在执行完毕后将该操作对应的alert插入到alert队列,用户需要使用session::pop_alert获取操作的结果。从单纯使用库(简单来说就是从hpp和lib文件开发而不关心libed2k怎么实现也无需去深度定制)的开发者而言编写一个ed2k客户端需要做的事情就是设置libed2k会话参数,连接服务器并启动一个会话。添加任务,接收session的各种通知,然后根据这些通知决定下一步该执行什么。

 

2.4.1 alert介绍

 

alert类是所有通知类的基类,其定义为:

class alert 

{ 

public: 

// only here for backwards compatibility 

enum severity_t 

{ debug, info, warning, critical, fatal, none }; 

enum category_t 

{ 

    error_notification = 0x1, 

    peer_notification = 0x2,

    port_mapping_notification = 0x4, 

    storage_notification = 0x8, 

    tracker_notification = 0x10, 

    debug_notification = 0x20, 

    status_notification = 0x40, 

    progress_notification = 0x80, 

    ip_block_notification = 0x100, 

    performance_warning = 0x200, 

    server_notification = 0x400, 

    dht_notification = 0x400, 

    stats_notification = 0x800, 

    all_categories = 0xffffffff 

}; 

    alert(); 

    virtual ~alert(); 

    // a timestamp is automatically created in the constructor 

    ptime timestamp() const; 

    virtual char const* what() cons
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值