从零开始学习比特币开发(七):P2P网络建立流程之生成地址对并连接到指定地址
Author Image 区小白 2018-10-18 10:56453
本节继续讲解比特币P2P网络建立流程,这节讲解的线程为’ThreadOpenAddedConnections’,它的作用是生成地址对并连接到指定地址。
本文可以结合比特币系统启动的的第12步的讲解来看,可以更加系统的了解比特币系统启动的过程。
P2P 网络的建立是在比特币系统启动的第 12 步,最后时刻调用 CConnman::Start 方法开始的。
本部分内容在 net.cpp、net_processing.cpp 等文件中。
下面开始讲解各个线程的具体处理。
1、ThreadSocketHandler
见文章从零开始学习比特币(五)–P2P网络建立的流程之套接字的读取和发送
2、ThreadDNSAddressSeed
见文章从零开始学习比特币(六)–P2P网络建立的流程之查询DNS节点
3、ThreadOpenAddedConnections
这个线程的主要作用是生成地址对象,并且调用 OpenNetworkConnection 方法,连接到指定地址。
线程定义在 net.cpp 文件的 1959 行。下面我们开始进行具体的解读。
线程的主体是一个 while 循环。在循环中进行下面的处理。
调用 GetAddedNodeInfo 方法,获取所有的节点信息。本方法返回所有的节点信息,其中即有已连接的,也有未连接的地址。
首先,生成保存节点信息的容器变量 ret 和保存地址字符串的列表对象 lAddresses。然后把 vAddedNodes 集合中的所有地址拷贝到 lAddresses中。
std::vector<AddedNodeInfo> ret;
std::list<std::string> lAddresses(0);
{
LOCK(cs_vAddedNodes);
ret.reserve(vAddedNodes.size());
std::copy(vAddedNodes.cbegin(), vAddedNodes.cend(), std::back_inserter(lAddresses));
}
遍历所有的节点(vNodes 节点容器),进行下面处理。如果当前节点的地址是有效的,则加入 mapConnected map 中,Key 为当前节点的地址,值标明当前节点是否为入站节点。获取当前节点的地址名称。如果名称不空,则放进 mapConnectedByName map 中,Key 为当前节点的地址名称,值为一个 std::pair 对象,其中第一个值表明当前节点是否为入站节点,第二个值为节点的地址。
std::map<CService, bool> mapConnected;
std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
{
LOCK(cs_vNodes);
for (const CNode* pnode : vNodes) {
if (pnode->addr.IsValid()) {
mapConnected[pnode->addr] = pnode->fInbound;
}
std::string addrName = pnode->GetAddrName();
if (!addrName.empty()) {
mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->fInbound, static_cast<const CService&>(pnode->addr));
}
}
}
遍历 lAddresses 变量,进行下面处理。根据当前地址和当前网络类型,生成一个 service 对象,类型为 CService,和一个节点信息对象。如果当前地址是 IP:Port 形式,那么查找 mapConnected 集合对应的地址。如果可以找到,则设置节点信息对象的相关属性。
如果当前地址是名称的形式,那么查找 mapConnectedByName 集合对应的地址。如果可以找到,则设置节点信息对象的相关属性。
把当前地址信息对象加入 ret 集合中。
http://m.8btc.com/bitebi-kaifa-2