主页 > imtoken国内怎么下 > 从零开始学比特币开发(七):P2P网络建立过程中生成地址对并连接指定地址

从零开始学比特币开发(七):P2P网络建立过程中生成地址对并连接指定地址

imtoken国内怎么下 2023-03-25 06:42:34

本节继续讲解比特币P2P网络建立过程。 本节讲解的线程为“ThreadOpenAddedConnections”,用于生成地址对,连接指定地址。 本文可以结合比特币系统启动第12步的讲解,让大家对比特币系统启动过程有一个更系统的认识。

P2P网络的建立是在比特币系统启动第12步的最后时刻调用的? CConnman:开始? 方法开始。

本节内容是什么? net.cpp,net_processing.cpp? 在文件中等待。

下面开始讲解各个线程的具体处理。

1.线程套接字处理器

当前连接的比特币测试网络信息_比特币网络交易平台_808比特币创始人颜万卫 炮制比特币风险大

参见文章从零开始学习比特币(五)——P2P网络建立过程中socket的读取和发送

2.线程n地址种子

参见文章从零开始学习比特币(6)——P2P网络建立过程中查询DNS节点【x OpenNetworkConnection? 连接到指定地址的方法。

当前连接的比特币测试网络信息_比特币网络交易平台_808比特币创始人颜万卫 炮制比特币风险大

线程在? net.cpp? 文件的第 1959 行。 让我们先详细阅读一下。

线程的主体是一个 ? 什么时候? 循环。 以下处理循环执行。

给...打电话? 获取添加节点信息? 获取所有节点信息的方法。 此方法返回所有节点信息,包括已连接和未连接的地址。 首先,生成一个保存节点信息的容器变量? 退役? 并列出包含地址字符串的对象? 梯子。 然后呢? v 添加节点? 将集合中的所有地址复制到? 穿梯子。 STD:向量ret; STD:列表阶梯(0); { 锁(cs_vAddedNodes); ret.reserve(vaddednodes.size()); std:copy(vAddedNodes.cbegin(), vAddedNodes.cend(), STD: back_inserter(lAddresses)); } 遍历所有节点(vNodes?节点容器),进行如下处理。 如果当前节点的地址有效,加入? 地图已连接? 图中Key为当前节点的地址当前连接的比特币测试网络信息,value表示当前节点是否为入节点。 获取当前节点的地址名称。 如果名字不为空,直接填进去? 地图连接名称? 图中Key是当前节点的地址名,value是? 性病:一对? 对象,其中第一个值表示当前节点是否为入站节点,第二个值是该节点的地址。 STD:地图地图连接; 性病:地图

当前连接的比特币测试网络信息_808比特币创始人颜万卫 炮制比特币风险大_比特币网络交易平台

地图连接名称; { 锁(cs_vNodes); for (const CNode * pnode:vNodes) { if (pnode-addr. is valid()) { map connected[pnode-addr] = pnode-fin bound; } STD: string addrName = pnode-get addr name(); 如果 (!addrName.empty()) { mapConnectedByName[STD:move(addrName)] = STD:make_pair(pnode-fInbound, static_cast(pnode-addr)); } }} 遍历? l地址? 变量,并进行以下处理。 根据当前地址和当前网络类型,生成一个? 服务? 对象的类型? CService 和一个节点信息对象。 如果当前地址是IP:Port的形式,那么检查? 地图已连接? 对应集合的地址。 如果可以找到,则设置节点信息对象的相关属性。

如果当前地址是名字的形式,那么检查? 地图连接名称? 对应集合的地址。 如果可以找到,则设置节点信息对象的相关属性。 添加当前地址信息对象? 退役? 在收藏中。 for(const STD:string stradd node:lAddresses){ CService 服务(查找数字(stradd node.c_str(),Params().GetDefaultPort())); AddedNodeInfo 添加节点 { stradd node,CService(),false, false }; if (service.IsValid()) { // strAddNode 是一个 IP:port auto it = map connected. 查找(服务); if (it != map connected.end()) { 添加节点。 解析地址=服务; 添加了 node.fc connected = true; 添加节点。 fin bound = it-second; } } else { //strAddNode 是一个名字 auto it = mapconnectedbyname.find(straddnode); if (it!= mapconnectedbyname.end( )){ 添加了 node.resolved address=it-second.second; 添加了 node.fc connected=true; 添加了 node.fin bound=it-second.first; } } ret.launte_back(STD:move(added node) ); 返回ret? 收集。

遍历所有节点信息。 如果当前节点未连接,则进行如下处理:生成地址对象? 地址,类型? 女服务员。 在通电话? 打开网络连接? 连接到当前节点的方法。 for(const AddedNodeInfo info:vInfo){ if(!info.fConnected) { if(!Grant.TryAcquire()) { // 如果我们已经用完了我们的信号量并且需要一个新的,我们不会在这里等待,因为addednodeinfo 状态可能会在我们等待时发生变化。 休息; } tried = true CAD 地址 addr(CService(), NODE_NONE); OpenNetworkConnection(addr, false, grant, info.strAddedNode.c_str(), false, false, true); 如果 (!interrupt net.sleep_for (std:chrono:milliseconds(500))) 返回; } }

比特币网络交易平台_当前连接的比特币测试网络信息_808比特币创始人颜万卫 炮制比特币风险大

让我们详细看看? 打开网络连接? 功能处理。

如果? 网络断开? 如果为真当前连接的比特币测试网络信息,则返回。 如果网络不活动则返回 (fNetworkActive? False)。 如果(中断网){ 返回; } 如果(!fNetworkActive){ 返回; } 如果参数? pszDest? Null(当前节点信息的地址),进一步,如果要连接的节点是本地的、已连接的或禁止的,则返回。 如果参数? pszDest? 不为空,如果节点已连接,则另外返回。 if (!pszDest) { if (is local(addr connect) | | FindNode(static_cast(addr connect)) | | is banned(addr connect) | | FindNode(addr connect.ToStringIPPort())) 返回; } else if(FindNode(STD:string(pszDest))) 返回; 称呼? 连接节点? 方法,连接到指定的地址,并返回对等节点。 C节点? 目的。 如果连接失败,它将返回。 如果参数? 授予出站? 对象存在,调用它。 搬去? 处理方法。 如果参数? f 一次射击? 如果为真,设置对等方的? f 一次射击? 属性为真。

如果是临时探测节点(参数fFeeler?True),设置对端节点的? 费雷尔? 属性为真。 如果是手动连接,设置? m_manual_connect? 属性为真。 调用网络事件处理程序? 初始化节点? 初始化对等节点的方法。 具体代码在哪里? net_processing.cpp? 文件第611行,如下图所示: void peer logic finalization:initialize node(cnode * pnode){ c address addr=pnode-addr; STD:string addrName=pnode-get addr name(); NodeId NodeId=pnode-GetId( ); { 锁(cs_main); mapnodestate.launte_hint(mapnodestate.end(), std:piece_construct, std:forward_as_tuple(nodeid), std:forward_as_tuple(addr, std:move(addrName))); } if (!pnode-fin bound) pushNodeVision(pnode, connman, GetTime()); }

当前连接的比特币测试网络信息_比特币网络交易平台_808比特币创始人颜万卫 炮制比特币风险大

代码的主要动作是检查该节点是否是出站节点,即连接到其他对等点,如果是,则调用? 推送节点版本? 发送版本信息的方法。 具体消息处理部分。 将生成的对等点保存到? 虚拟节点? vector.上面解释

3.1、连接节点? 打开网络连接? 函数“3.调用?ConnectNode?方法,连接到指定地址,返回对端节点.CNode?对象”,我提到了'connect node'方法,它负责连接到特定的对端节点。 下面我们来看看具体的治疗方法。

如果参数? pszDest? 如果是空指针,处理如下:如果要连接的地址是本地地址,直接返回空指针。 给...打电话? 查找节点? 查看指定节点是否存在的方法。 如果存在,即已连接,则返回一个空指针。 if(pszDest==null ptr){ if(is local(addr connect)) return null ptr; // 查找现有连接 CNode * pnode = FindNode(static_cast(addr connect)); if (pnode) { LogPrintf( '打开新连接失败,已经连接\n'); 返回 nullptr }} 如果参数? pszDest? 不是空指针,它被调用。 寻找? 方法来查找/生成对应于地址字符串的地址对象。 如果找到,则执行以下处理: 生成要连接的地址对象。 如果地址地址对象无效,则返回一个空指针。 给...打电话? 查找节点? 方法来查找相应的地址对象。 如果存在,即已连接,则返回一个空指针。 这个地方解析要连接的地址字符串,生成要连接的地址对象 const int default_port=Params().GetDefaultPort(); 如果(PSZ 目的地){ STD:已解析的矢量; 如果(查找(pszDest,已解决,默认端口,fNameLookup!HaveNameProxy(),256)!已解决。

empty()) { addr connect = CAD 地址(resolved[GetRand(resolved.size())], NODE_NONE); if(!addrConnect.IsValid()) { LogPrint(BCLog: NET, 'Resolver returned invalid address %s(for %s' add connect.ToString(), PSZ dest); return nullptr } lock(cs_vNodes); CNode *pnode = FindNode(static_cast(addr connect)); if(pnode){ pnode-MaybeSetAddrName(STD:string(pszDest)); LogPrintf('无法打开新的连接动作,已经连接\n"); return nullptr;} } } 如果要连接的地址对象有效,则进行如下处理,调用?GetProxy?方法返回代理类型,如果方法返回true,即存在代理,则调用?CreateSocket?方法创建一个proxy socket,如果创建成功,调用?ConnectThroughProxy?小编2022节点。

如果不存在代理,则调用?CreateSocket? 创建对等方套接字的方法。 如果成功创建,调用?ConnectSocketDirectly? 方法直接连接到对等节点。 bool proxyConnectionFailed = false; 如果 (GetProxy(addrConnect.GetNetwork(), proxy)) { hSocket = CreateSocket(proxy.proxy); 如果(hSocket == INVALID_SOCKET){return nullptr; } connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP( ), addrConnect.GetPort(), hSocket, nConnectTimeout, &proxyConnectionFailed);} else { // 不需要代理(没有为目标网络设置) hSocket = CreateSocket(addrConnect); 如果(hSocket == INVALID_SOCKET){return nullptr; } connected = ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout, manual_connection);}if (!proxyConnectionFailed) { // 如果尝试连接到节点,并且失败(如果有)不是由连接到代理的问题引起的,椰棕雨衣网小编2022将此标记为一次尝试。 addrman.Attempt(addrConnect, fCountFailure);} 如果要连接的字符串不为空且有代理,则:调用?CreateSocket? 为代理生成套接字的方法。

然后,调用 ?ConnectThroughProxy 方法通过代理连接到指定的对等点。 hSocket = CreateSocket(proxy.proxy);if (hSocket == INVALID_SOCKET) { return nullptr;}std::string host;int port = default_port;SplitHostPort(std::string(pszDest), port, host);连接= ConnectThroughProxy (代理、主机、端口、hSocket、nConnectTimeout、nullptr); 如果以上都没有连接到master,关闭套接字并返回一个空指针。 如果 (!connected) {CloseSocket(hSocket);返回 nullptr; 最后,生成并返回主节点对象。 NodeId id = GetNewNodeId(); uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); CAddress addr_bind = GetBindAddress(hSocket); CNode* pnode = new CNode(id, nLocalServices, GetaddBestHeight(), hSocket, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest 2022 pszDest ? pszDest : "", false); pnode->AddRef(); 返回节点; 我是曲小白,Ulord全球社区联盟(友德社区)核心区块链技术开发者,对比特币、以太坊、EOS Dash、Rsk、Java、Nodejs、PHP、Python、C++有深入研究希望能聚集更多区块链开发者一起学习共同进步。 为了更高效的交流和讨论区块链开发过程中遇到的问题,请在帖子下方留言,并附上以上问题的答案。