国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

剝開比原看代碼02:比原啟動后去哪里連接別的節點

olle / 2926人閱讀

摘要:對應于繼續,加入了超時對應于終于到了包的調用,開始真正去連接這個種子節點了,到這里,我們可以認為這個問題解決了。

作者:freewind

比原項目倉庫:

Github地址:https://github.com/Bytom/bytom

Gitee地址:https://gitee.com/BytomBlockc...

最開始我對于這個問題一直有個疑惑:區塊鏈是一個分布式的網絡,那么一個節點啟動后,它怎么知道去哪里找別的節點從而加入網絡呢?

看到代碼之后,我才明白,原來在代碼中硬編碼了一些種子地址,這樣在啟動的時候,可以先通過種子地址加入網絡。雖然整個網絡是分布式的,但是最開始還是需要一定的中心化。

預編碼內容

對于配置文件config.toml,比原的代碼中硬編碼了配置文件內容:

config/toml.go#L22-L45

var defaultConfigTmpl = `# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml
fast_sync = true
db_backend = "leveldb"
api_addr = "0.0.0.0:9888"
`

var mainNetConfigTmpl = `chain_id = "mainnet"
[p2p]
laddr = "tcp://0.0.0.0:46657"
seeds = "45.79.213.28:46657,198.74.61.131:46657,212.111.41.245:46657,47.100.214.154:46657,47.100.109.199:46657,47.100.105.165:46657"
`

var testNetConfigTmpl = `chain_id = "testnet"
[p2p]
laddr = "tcp://0.0.0.0:46656"
seeds = "47.96.42.1:46656,172.104.224.219:46656,45.118.132.164:46656"
`

var soloNetConfigTmpl = `chain_id = "solonet"
[p2p]
laddr = "tcp://0.0.0.0:46658"
seeds = ""
`

可以看出,對于不同的chain_id,預設的種子是不同的。

當然,如果我們自己知道某些節點的地址,也可以在初始化生成config.toml后,手動修改該文件添加進去。

啟動syncManager

那么,比原在代碼中是使用這些種子地址并連接它們的呢?關鍵在于,連接的代碼位于SyncManager中,所以我們要找到啟動syncManager的地方。

首先,當我們使用bytomd node啟動后,下面的函數將被調用:

cmd/bytomd/commands/run_node.go#L41

func runNode(cmd *cobra.Command, args []string) error {
    // Create & start node
    n := node.NewNode(config)
    if _, err := n.Start(); err != nil {
        // ...
    }
    // ...
}

這里調用了n.Start,其中的Start方法,來自于Node所嵌入的cmn.BaseService

node/node.go#L39

type Node struct {
    cmn.BaseService
    // ...
}

所以n.Start對應的是下面這個方法:

vendor/github.com/tendermint/tmlibs/common/service.go#L97

func (bs *BaseService) Start() (bool, error) {
    // ...
    err := bs.impl.OnStart()
    // ...
}

在這里,由于bs.impl對應于Node,所以將繼續調用Node.OnStart():

node/node.go#L169

func (n *Node) OnStart() error {
    // ...
    n.syncManager.Start()
    // ...
}

可以看到,我們終于走到了調用了syncManager.Start()的地方。

syncManager中的處理

然后就是在syncManager內部的一些處理了。

它主要是除了從config.toml中取得種子節點外,還需要把以前連接過并保存在本地的AddressBook.json中的節點也拿出來連接,這樣就算預設的種子節點失敗了,也還是有可能連接上網絡(部分解決了前面提到的中心化的擔憂)。

syncManager.Start()對應于:

netsync/handle.go#L141

func (sm *SyncManager) Start() {
    go sm.netStart()
    // ...
}

其中sm.netStart(),對應于:

netsync/handle.go#L121

func (sm *SyncManager) netStart() error {
    // ...
    // If seeds exist, add them to the address book and dial out
    if sm.config.P2P.Seeds != "" {
        // dial out
        seeds := strings.Split(sm.config.P2P.Seeds, ",")
        if err := sm.DialSeeds(seeds); err != nil {
            return err
        }
    }
    // ...
}

其中的sm.config.P2P.Seeds就對應于config.toml中的seeds。關于這兩者是怎么對應起來的,會在后面文章中詳解。

緊接著,再通過sm.DialSeeds(seeds)去連接這些seed,這個方法對應的代碼位于:

netsync/handle.go#L229

func (sm *SyncManager) DialSeeds(seeds []string) error {
    return sm.sw.DialSeeds(sm.addrBook, seeds)
}

其實是是調用了sm.sw.DialSeeds,而sm.sw是指Switch。這時可以看到,有一個叫addrBook的東西參與了進來,它保存了該結點之前成功連接過的節點地址,我們這里暫不多做討論。

Switch.DialSeeds對應于:

p2p/switch.go#L311

func (sw *Switch) DialSeeds(addrBook *AddrBook, seeds []string) error {
    // ...
    perm := rand.Perm(len(netAddrs))
    for i := 0; i < len(perm)/2; i++ {
        j := perm[i]
        sw.dialSeed(netAddrs[j])
    }
   // ...
}

這里引入了隨機數,是為了將發起連接的順序打亂,這樣可以讓每個種子都獲得公平的連接機會。

sw.dialSeed(netAddrs[j])對應于:

p2p/switch.go#L342

func (sw *Switch) dialSeed(addr *NetAddress) {
    peer, err := sw.DialPeerWithAddress(addr, false)
    // ...
}

sw.DialPeerWithAddress(addr, false)又對應于:

p2p/switch.go#L351

func (sw *Switch) DialPeerWithAddress(addr *NetAddress, persistent bool) (*Peer, error) {
    // ...
    log.WithField("address", addr).Info("Dialing peer")
    peer, err := newOutboundPeerWithConfig(addr, sw.reactorsByCh, sw.chDescs, sw.StopPeerForError, sw.nodePrivKey, sw.peerConfig)
    // ...
}

其中的persistent參數如果是true的話,表明這個peer比較重要,在某些情況下如果斷開連接后,還會嘗試重連。如果persistentfalse的,就沒有這個待遇。

newOutboundPeerWithConfig對應于:

p2p/peer.go#L69

func newOutboundPeerWithConfig(addr *NetAddress, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *PeerConfig) (*Peer, error) {
    conn, err := dial(addr, config)
    // ...
}

繼續dial,加入了超時:

p2p/peer.go#L284

func dial(addr *NetAddress, config *PeerConfig) (net.Conn, error) {
    conn, err := addr.DialTimeout(config.DialTimeout * time.Second)
    if err != nil {
        return nil, err
    }
    return conn, nil
}

addr.DialTimeout對應于:

p2p/netaddress.go#L141

func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) {
    conn, err := net.DialTimeout("tcp", na.String(), timeout)
    if err != nil {
        return nil, err
    }
    return conn, nil
}

終于到了net包的調用,開始真正去連接這個種子節點了,到這里,我們可以認為這個問題解決了。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/24160.html

相關文章

  • 剝開原看代碼01:初始化時生成的配置文件在哪兒

    摘要:所以這個文章系列叫作剝開比原看代碼。所以我的問題是比原初始化時,產生了什么樣的配置文件,放在了哪個目錄下下面我將結合源代碼,來回答這個問題。將用來確認數據目錄是有效的,并且將根據傳入的不同,來生成不同的內容寫入到配置文件中。 作者:freewind 比原項目倉庫: Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee...

    felix0913 評論0 收藏0
  • 剝開原看代碼06:比原是如何把請求區塊數據的信息發出去的

    摘要:作者比原項目倉庫地址地址在前一篇中,我們說到,當比原向其它節點請求區塊數據時,會發送一個把需要的區塊告訴對方,并把該信息對應的二進制數據放入對應的通道中,等待發送。這個就是真正與連接對象綁定的一個緩存區,寫入到它里面的數據,會被發送出去。 作者:freewind 比原項目倉庫: Github地址:https://github.com/Bytom/bytom Gitee地址:https:...

    CloudwiseAPM 評論0 收藏0
  • 剝開原看代碼05:如何從比原節點拿到區塊數據?

    摘要:作者比原項目倉庫地址地址在前一篇中,我們已經知道如何連上一個比原節點的端口,并與對方完成身份驗證。代碼如下可以看到,首先是從眾多的中,找到最合適的那個。到這里,我們其實已經知道比原是如何向其它節點請求區塊數據,以及何時把信息發送出去。 作者:freewind 比原項目倉庫: Github地址:https://github.com/Bytom/bytom Gitee地址:https://...

    233jl 評論0 收藏0
  • 剝開原看代碼03:比原是如何監聽p2p端口的

    摘要:啟動直到進入所以我們首先需要知道,比原在源代碼中是如何啟動,并且一步步走進了的世界。后面省略了一些代碼,主要是用來獲取當前監聽的實際以及外網,并記錄在日志中。 比原是如何監聽p2p端口的 我們知道,在使用bytomd init --chain_id mainnet/testnet/solonet初始化比原的時候,它會根據給定的chain_id的不同,使用不同的端口(參看config/t...

    layman 評論0 收藏0
  • 剝開原看代碼10:比原是如何通過/create-key接口創建密鑰的

    摘要:如果傳的是,就會在內部使用默認的隨機數生成器生成隨機數并生成密鑰。使用的是,生成的是一個形如這樣的全球唯一的隨機數把密鑰以文件形式保存在硬盤上。 作者:freewind 比原項目倉庫: Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockc... 在前一篇,我們探討了從瀏覽器的dashb...

    ccj659 評論0 收藏0

發表評論

0條評論

olle

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<