美文网首页区块链研习社
比特币源码阅读:比特币网络(一)

比特币源码阅读:比特币网络(一)

作者: 沙漠中的猴 | 来源:发表于2017-12-04 20:43 被阅读0次

比特币网络部分主要包含在net.cpp和netbase.cpp文件中,netbase.cpp内主要是一些辅助函数,因此我们主要阅读net.cpp文件中的几个重要函数

01:ThreadDNSAddressSeed

// src/net.cpp 
void CConnman::ThreadDNSAddressSeed()
{
    // goal: only query DNS seeds if address need is acute
    // Avoiding DNS seeds when we don't need them improves user privacy by
    //  creating fewer identifying DNS requests, reduces trust by giving seeds
    //  less influence on the network topology, and reduces traffic to the seeds.
/*该方法提示,只有在急需接入网络的时候再使用DNS seed。这样能避免DNS seed连接数过多,也能提高用户的隐私。所以尽量不要直接连接DNS seed。*/
    if ((addrman.size() > 0) &&
        (!gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED))) {
        if (!interruptNet.sleep_for(std::chrono::seconds(11)))
            return;

        LOCK(cs_vNodes);
        int nRelevant = 0;
        for (auto pnode : vNodes) {
            nRelevant += pnode->fSuccessfullyConnected && ((pnode->nServices & nRelevantServices) == nRelevantServices);
        }
        if (nRelevant >= 2) {
            LogPrintf("P2P peers available. Skipped DNS seeding.\n");
            return;
        }
    }

    const std::vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
    int found = 0;

    LogPrintf("Loading addresses from DNS seeds (could take a while)\n");

    for (const CDNSSeedData &seed : vSeeds) {
        if (interruptNet) {
            return;
        }
        if (HaveNameProxy()) {
            AddOneShot(seed.host);
        } else {
            std::vector<CNetAddr> vIPs;
            std::vector<CAddress> vAdd;
            ServiceFlags requiredServiceBits = nRelevantServices;
            std::string host = GetDNSHost(seed, &requiredServiceBits);
            CNetAddr resolveSource;
            if (!resolveSource.SetInternal(host)) {
                continue;
            }
            if (LookupHost(host.c_str(), vIPs, 0, true))
            {
                for (const CNetAddr& ip : vIPs)
                {
                    int nOneDay = 24*3600;
                    CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits);
                    addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
                    vAdd.push_back(addr);
                    found++;
                }
                addrman.Add(vAdd, resolveSource);
            }
        }
    }

    LogPrintf("%d addresses found from DNS seeds\n", found);
}

将这个函数拆分成多个段落来分析。

第一段代码:

if ((addrman.size() > 0) &&
        (!gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED))) {
        if (!interruptNet.sleep_for(std::chrono::seconds(11)))
            return;

        LOCK(cs_vNodes);
        int nRelevant = 0;
        for (auto pnode : vNodes) {
            nRelevant += pnode->fSuccessfullyConnected && ((pnode->nServices & nRelevantServices) == nRelevantServices);
        }
        if (nRelevant >= 2) {
            LogPrintf("P2P peers available. Skipped DNS seeding.\n");
            return;
        }
    }

addrman.size()函数在/src/addrman.h中声明。返回IP地址管理器CAddrMan中的IP地址个数。
-forcednsseed参数指强制通过DNSseed来接入网络。DEFAULT_FORCEDNSSEED默认是false。
interruptNet.sleep_for(std::chrono::seconds(11)线程阻塞11秒。

cs_vNodes声明在/src/net.h文件中

// src/net.h
mutable CCriticalSection cs_vNodes;

CCriticalSection类CCriticalSection的对象表示一个"临界区",它是一个用于同步的对象,同一时刻只允许一个线程存取资源或代码区。类似于互斥锁功能。
vNodes声明在/src/net.h

// src/net.h
std::vector<CNode*> vNodes;

系统定义了节点数组( vector<CNode*> vNodes),包含了连接的所有节点。当节点连接上,则把此节点添加到节点数组中;断开连接后,从节点数组中移除此节点。

这段代码的意思是:如果IP地址管理器CAddrMan中IP地址大于0,且没有指定-forcednsseed参数,线程阻塞11秒。然后锁定cs_vNodes,遍历vNodes节点数组,如果成功连接的节点个数大于等于2。则打印"P2P节点是有效的,跳过DNS seeding阶段"

剩余部分代码:

const std::vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
    int found = 0;

    LogPrintf("Loading addresses from DNS seeds (could take a while)\n");

    for (const CDNSSeedData &seed : vSeeds) {
        if (interruptNet) {
            return;
        }
        if (HaveNameProxy()) {
            AddOneShot(seed.host);
        } else {
            std::vector<CNetAddr> vIPs;
            std::vector<CAddress> vAdd;
            ServiceFlags requiredServiceBits = nRelevantServices;
            std::string host = GetDNSHost(seed, &requiredServiceBits);
            CNetAddr resolveSource;
            if (!resolveSource.SetInternal(host)) {
                continue;
            }
            if (LookupHost(host.c_str(), vIPs, 0, true))
            {
                for (const CNetAddr& ip : vIPs)
                {
                    int nOneDay = 24*3600;
                    CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits);
                    addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
                    vAdd.push_back(addr);
                    found++;
                }
                addrman.Add(vAdd, resolveSource);
            }
        }
    }

    LogPrintf("%d addresses found from DNS seeds\n", found);

这段代码的意思是通过DNS seed列表来获取对应的IP地址、端口号存放在IP管理器CAddrMan中。

相关文章

  • 比特币源码研读

    forest21000版 比特币源码研读之一比特币源码研读之二比特币源码研读之三比特币源码研读之四比特币源码研读之...

  • 比特币源码阅读:比特币网络(一)

    比特币网络部分主要包含在net.cpp和netbase.cpp文件中,netbase.cpp内主要是一些辅助函数,...

  • 在家宅着,不如了解一下比特币矿机挖矿小知识。

    ​​何为比特币挖矿? 比特币的挖矿机制是整个比特币系统赖以生存的基础,为了比特币网络能够安全运行,比特币网络平均每...

  • 比特币源码阅读--比特币网络(一)--简介

    比特币网络可以分成三个部分来查看 网络协议 网络节点 网络初始化和关闭 网络协议 消息 消息头 消息类型 命令 命...

  • 开始研读比特币1

    1,进入比特币源码目录,先读读编译doc/build-unix.md,查看比特币源码如何编译,了解比特币的依赖库,...

  • 比特币源码研读(2)—— 钱包

    导读: 比特币钱包中没有存储任何比特币,而是存的取比特币的钥匙。比特币被记录在比特币网络的区块链中。 用户...

  • 区块链中的常见基本概念,你知道吗?

    比特币 “比特币”既可以指这种虚拟货币单位,也指比特币网络或者网络节点使用的比特币软件。 区块 一个区块就是若干交...

  • 比特币是骗局?

    “比特币是骗局,比特币就是割韭菜,比特币就是傻子才会买的。”最近随着比特币的大涨,在网络上充斥着大量贬低比特币的言...

  • 比特币(6):挖矿

    比特币(1):从一个简单支付场景说起 比特币(2):私钥、公钥和地址 比特币(3):交易详解 比特币(4):网络架...

  • 【#1-陈雪昊】我所认识的比特币

    一.中本聪设计了比特币,比特币是一个去中心化的账本,所有的比特币节点都是等权的,比特币网络由全体比特币用户共同控制...

网友评论

    本文标题:比特币源码阅读:比特币网络(一)

    本文链接:https://www.haomeiwen.com/subject/ruetixtx.html