Libtorrent源代码阅读小札
来源:互联网 发布:紫光手电筒下载软件 编辑:程序博客网 时间:2024/04/29 12:25
ses.start_dht()->ses_imp.start_dht(),session_impl是session的实现。跟踪进去,m_dht = new dht::dht_tracker(m_io_service, m_dht_settings, m_listen_interface.address(), startup_state),session_impl会在start_dht里面创建一个dht_tracker对象,这里的参数需要好好看一下,首先是m_io_service,这是boost::asio库中的一个对象,简单来说就是提供io服务,每一个利用boost::asio库的程序都需要拥有这样一个对象,它负责与操作系统内核的通信互动,有点类似于手机中的手机卡一样,虽然手机已经实现了无线通信的功能,但是,需要手机卡才能加入到虚线网络,才能获取我们所需的服务。可以看到,这个io_service对象放在session_impl中,意味着一个session只会拥有一个io_service对象。第二个参数相当于dht网络的配置文件。第三个参数为IP地址。第四个参数为携带启动节点信息的对象。继续跟踪,看看dht_tracker在构造函数中会做些什么事。跟踪进去后发现,dht_tracker在构造函数中会进行一系列的初始化,那么我们挑选几个比较重要的初始化动作,看看这些传进去的参数最终都作为何用。第一个:m_strand(ios),原来dht_tracker会维护一个boost::asio::strand对象,此对象有何用处?它是用来保证,通过strand对象包装的threads,对线性有序的执行,主要是用来实现线程同步的,这个先分析到这里,有时间再去深究一下。第二个: m_socket(ios, udp::endpoint(listen_interface, settings.service_port)),我们看到了传进来的IP地址,以及dht_setting原来可以初始化一个udp套接字。第三个:m_dht(bind(&dht_tracker::send_packet, this, _1), settings, read_id(bootstrap)),m_dht何许物也?原来它是一个node_impl对象,这名字取得还真是让人难以望文生义啊!dht_tracker又要去初始化node_impl对象,我们现在来稍微理一理dht_tracker和node_impl之间的关系,查看一下接口,我们可以直观的认为dht_tracker是用来管理dht网络和racker通信的,从实现看来,dht网络的实现需要借助于node_impl,至于更深层的关系有待接下来的深入跟踪。来看参数,第一个参数为一个函数对象,我们有必要了解一下此函数对象的signature,我借用boost来表达一下:boost::function<void(msg const&)>。直观来看,此函数对象的作用应该是发送一个msg,啊呀,好像找到了libtorrent数据通信的一点端倪了,如果没有猜错,那么send_packet里面应该能找到我们熟悉的socket通信了,真是不容易啊。带着激动的心情,我们进去看看。哇哇哇,果然不失所望啊,这里面别有洞天啊,看到了这么多熟悉的字眼“token”,“query”,“info_hash”,“ping”,“find_node”,“get_peer”……哈哈,熟悉dht的朋友应该会很兴奋,其余的就不用我说了吧。接下来就有一个问题了,这个函数究竟会被谁调用呢?我们来看看,它把send_packet包装成一个函数对象,作为node_impl对象的初始化参数传递出去,难道此函数会由node_impl来调用?继续前进。Node_impl对象的构造函数看起来稍微清爽一些,我们一个一个来看,m_settings(settings):这个setting就是dht_setting,传的够远啊,从session一路走来,经过session_impl,dht_tracker,这会又到了这里,真想它的终点在那里,此为后话,留为存照。m_id(node_id ? *node_id : generate_id()):这个不用多说,node_id是也。m_table(m_id, 8, settings):哈哈,dht路由表,终于看到你啦。m_rpc(bind(&node_impl::incoming_request, this, _1), m_id, m_table, f):原来node_impl还会去初始化一个rpc_manager对象,哇,又看到了久违的boost::bind了,不用说又有函数对象产生了,看看这次又会有什么发现。还是用boost::function来表述吧,查证以后原来还是boost::function<void(msg const&)>,我们可以看到这次包装的是node_impl::incoming_request,那么里面又会发生什么事情呢?会不会又有惊喜啊?来看看吧。哇哇,熟悉的switch..case语句,还用说什么,无以言表啊……到这里我们找到了dht网络最核心的send和receive。下面只需要知道究竟是谁调用的,就彻底明晰了。好,这样来看,这两个函数对象都会传送给rpc_manager,这个rcp_manager到底是怎样一个神秘角色,dht_tracker和node_impl里面的函数都归它调用,让我们来揭开它的神秘面纱吧。跟踪到rpc_manager的构造函数,发现也只是些初始化动作,其中我们最关心的两个函数对象分别被赋值给m_send和m_incoming。得,追踪到这里,已经到了绝路了。那么,这两个对象又是什么时候调用的呢?虽然已经没有明显的线索,但是我们可以大致确定这两个函数对象只能是rpc_manager来调用了,那就ctrl+f吧,来看看他们都会出现在哪些地方。
Rpc_manager::invoke(int message_id, udp::endpoint target_addr, shared_ptr<observer> o)
{
……
o->send(m);
……
m_send(m);
……
}
Rpc_manager::reply(msg& m, msg const& reply_to)
{
……
m_send(m);
……
}
void rpc_manager::reply_with_ping(msg& m, msg const& reply_to)
{
……
m_send(m);
……
}
哇,这么多地方调用,看来不能以这种方式跟踪了,我们得回退到client_test,接着往下读了。
///////////////////////////////////////////////////////
首先是Rpc_manager::Invoke(),调用者如下:
get_peers_observer::reply()
find_data_observer::invoke()
announce_fun
refresh::invoke_pings_or_finish()
refresh::invoke()
find_data::invoke()
closest_nodes::invoke()
- Libtorrent源代码阅读小札
- libtorrent
- 阅读源代码
- 源代码阅读
- 阅读源代码
- 阅读log4cplus源代码过程中的小知识点整理
- libtorrent分析
- libtorrent编译
- [转贴]如何阅读源代码
- 费尔防火墙源代码阅读
- OS161 源代码阅读-1
- OS161 源代码阅读-2
- 如何阅读项目源代码
- 怎样阅读源代码
- jflash源代码阅读
- 如何阅读开源代码
- Pentaho源代码阅读报告
- 如何阅读源代码
- 如何查看僵死进程
- 实用javaScript技术总结
- 3gp aac amr mp4 rm ram 等视频文件格式
- oracle新手入门指导之一——数据库表空间知识
- H.264码流的RTP打包格式
- Libtorrent源代码阅读小札
- C++导出模板类
- 如果我们不选择堕落,那么地狱的存在又有何意义?
- AAC AMR WAV MP3 采样率
- 宿主进程的介绍
- 11月以来广州二手豪宅成交下跌超三成(转载自中国新闻网)
- 新手入门:JSP注释
- Sql server中提高时间查询速度
- JS+CSS和图片美化下拉列表选择框(select)