启动server:
// Start begins accepting connections from peers. func (s *server) Start() { .... go s.peerHandler() if !cfg.DisableRPC { s.wg.Add(1) go s.rebroadcastHandler() s.rpcServer.Start() } // Start the CPU miner if generation is enabled. if cfg.Generate { s.cpuMiner.Start() } }
peerHandler负责启动节点的地址管理、同步管理、连接管理等,主要代码逻辑:
func (s *server) peerHandler() { s.addrManager.Start() s.syncManager.Start() srvrLog.Tracef("Starting peer handler") state := &peerState{ inboundPeers: make(map[int32]*serverPeer), persistentPeers: make(map[int32]*serverPeer), outboundPeers: make(map[int32]*serverPeer), banned: make(map[string]time.Time), outboundGroups: make(map[string]int), } if !cfg.DisableDNSSeed { connmgr.SeedFromDNS(activeNetParams.Params, defaultRequiredServices, btcdLookup, func(addrs []*wire.NetAddress) { s.addrManager.AddAddresses(addrs, addrs[0]) }) } go s.connManager.Start() out: for { select { // New peers connected to the server. case p := <-s.newPeers: s.handleAddPeerMsg(state, p) // Disconnected peers. case p := <-s.donePeers: s.handleDonePeerMsg(state, p) // Block accepted in mainchain or orphan, update peer height. case umsg := <-s.peerHeightsUpdate: s.handleUpdatePeerHeights(state, umsg) // Peer to ban. case p := <-s.banPeers: s.handleBanPeerMsg(state, p) // New inventory to potentially be relayed to other peers. case invMsg := <-s.relayInv: s.handleRelayInvMsg(state, invMsg) // Message to broadcast to all connected peers except those // which are excluded by the message. case bmsg := <-s.broadcast: s.handleBroadcastMsg(state, &bmsg) case qmsg := <-s.query: s.handleQuery(state, qmsg) case <-s.quit: // Disconnect all peers on server shutdown. state.forAllPeers(func(sp *serverPeer) { srvrLog.Tracef("Shutdown peer %s", sp) sp.Disconnect() }) break out } } ............. }
1.先执行节点地址管理
s.addrManager.Start()
主要逻辑:
func (a *AddrManager) Start() { ....... a.loadPeers() //从文件加载节点列表 ....... go a.addressHandler() }
go a.addressHandler()
定时保存地址列表到peer.json文件
2.启动同步管理
s.syncManager.Start()
主要逻辑是调用blockHandler()方法
func (sm *SyncManager) blockHandler() { out: for { select { case m := <-sm.msgChan: switch msg := m.(type) { case *newPeerMsg: sm.handleNewPeerMsg(msg.peer) case *txMsg: sm.handleTxMsg(msg) msg.reply <- struct{}{} case *blockMsg: sm.handleBlockMsg(msg) msg.reply <- struct{}{} case *invMsg: sm.handleInvMsg(msg) case *headersMsg: sm.handleHeadersMsg(msg) case *donePeerMsg: sm.handleDonePeerMsg(msg.peer) case getSyncPeerMsg: var peerID int32 if sm.syncPeer != nil { peerID = sm.syncPeer.ID() } msg.reply <- peerID case processBlockMsg: _, isOrphan, err := sm.chain.ProcessBlock( msg.block, msg.flags) if err != nil { msg.reply <- processBlockResponse{ isOrphan: false, err: err, } } msg.reply <- processBlockResponse{ isOrphan: isOrphan, err: nil, } case isCurrentMsg: msg.reply <- sm.current() case pauseMsg: // Wait until the sender unpauses the manager. <-msg.unpause default: log.Warnf("Invalid message type in block "+ "handler: %T", msg) } case <-sm.quit: break out } } sm.wg.Done() log.Trace("Block handler done") }
从通道case m := <-sm.msgChan:处理块消息,然后分发处理。
3.解析dns seed
connmgr.SeedFromDNS(activeNetParams.Params, defaultRequiredServices, btcdLookup, func(addrs []*wire.NetAddress) {
通过dns seed获得节点地址,将返回的节点地址添加到addrManager
4.连接管理
go s.connManager.Start()
启动连接管理,主要逻辑:
func (cm *ConnManager) Start() { ...... go cm.connHandler() if cm.cfg.OnAccept != nil { for _, listner := range cm.cfg.Listeners { cm.wg.Add(1) go cm.listenHandler(listner) } } for i := atomic.LoadUint64(&cm.connReqCount); i < uint64(cm.cfg.TargetOutbound); i++ { go cm.NewConnReq() } }
go cm.connHandler()
从cm.requests通道获得不同类型消息
go cm.listenHandler(listner)此方法会调用
go cm.cfg.OnAccept(conn)
OnAccept即server的inboundPeerConnected
func (s *server) inboundPeerConnected(conn net.Conn) { sp := newServerPeer(s, false) sp.isWhitelisted = isWhitelisted(conn.RemoteAddr()) sp.Peer = peer.NewInboundPeer(newPeerConfig(sp)) sp.AssociateConnection(conn) go s.peerDoneHandler(sp) }
sp.Peer = peer.NewInboundPeer(newPeerConfig(sp))
对peer进行初始配置,配置如下:
// newPeerConfig returns the configuration for the given serverPeer. func newPeerConfig(sp *serverPeer) *peer.Config { return &peer.Config{ Listeners: peer.MessageListeners{ OnVersion: sp.OnVersion, OnMemPool: sp.OnMemPool, OnTx: sp.OnTx, OnBlock: sp.OnBlock, OnInv: sp.OnInv, OnHeaders: sp.OnHeaders, OnGetData: sp.OnGetData, OnGetBlocks: sp.OnGetBlocks, OnGetHeaders: sp.OnGetHeaders, OnGetCFilters: sp.OnGetCFilters, OnGetCFHeaders: sp.OnGetCFHeaders, OnGetCFCheckpt: sp.OnGetCFCheckpt, OnFeeFilter: sp.OnFeeFilter, OnFilterAdd: sp.OnFilterAdd, OnFilterClear: sp.OnFilterClear, OnFilterLoad: sp.OnFilterLoad, OnGetAddr: sp.OnGetAddr, OnAddr: sp.OnAddr, OnRead: sp.OnRead, OnWrite: sp.OnWrite, // Note: The reference client currently bans peers that send alerts // not signed with its key. We could verify against their key, but // since the reference client is currently unwilling to support // other implementations' alert messages, we will not relay theirs. OnAlert: nil, }, NewestBlock: sp.newestBlock, HostToNetAddress: sp.server.addrManager.HostToNetAddress, Proxy: cfg.Proxy, UserAgentName: userAgentName, UserAgentVersion: userAgentVersion, UserAgentComments: cfg.UserAgentComments, ChainParams: sp.server.chainParams, Services: sp.server.services, DisableRelayTx: cfg.BlocksOnly, ProtocolVersion: peer.MaxProtocolVersion, } }以上On***会在收到消息时处理。
handleConnected消息会调用
go cm.cfg.OnConnection(connReq, msg.conn)
cm.cfg.OnConnection是在newserver时初始化的,即方法:
func (s *server) outboundPeerConnected(c *connmgr.ConnReq, conn net.Conn) { sp := newServerPeer(s, c.Permanent) p, err := peer.NewOutboundPeer(newPeerConfig(sp), c.Addr.String()) if err != nil { srvrLog.Debugf("Cannot create outbound peer %s: %v", c.Addr, err) s.connManager.Disconnect(c.ID()) } sp.Peer = p sp.connReq = c sp.isWhitelisted = isWhitelisted(conn.RemoteAddr()) sp.AssociateConnection(conn) go s.peerDoneHandler(sp) s.addrManager.Attempt(sp.NA()) }
sp.AssociateConnection(conn)
将sp(ServerPeer)对象与节点关联,并启动节点,主要逻辑:
func (p *Peer) AssociateConnection(conn net.Conn) { .... p.conn = conn p.timeConnected = time.Now() ...... go func() { if err := p.start(); err != nil { log.Debugf("Cannot start peer %v: %v", p, err) p.Disconnect() } }() }
异步启动节点p.start(),
func (p *Peer) start() error { log.Tracef("Starting peer %s", p) negotiateErr := make(chan error) go func() { if p.inbound { negotiateErr <- p.negotiateInboundProtocol() } else { negotiateErr <- p.negotiateOutboundProtocol() } }() // Negotiate the protocol within the specified negotiateTimeout. select { case err := <-negotiateErr: if err != nil { return err } case <-time.After(negotiateTimeout): return errors.New("protocol negotiation timeout") } log.Debugf("Connected to %s", p.Addr()) // The protocol has been negotiated successfully so start processing input // and output messages. go p.stallHandler() go p.inHandler() go p.queueHandler() go p.outHandler() go p.pingHandler() // Send our verack message now that the IO processing machinery has started. p.QueueMessage(wire.NewMsgVerAck(), nil) return nil }
go p.stallHandler()
节点是否失联的处理方法,维持一个deadline时间,每次连接请求会增大deadline时间
go p.inHandler()
接受消息的处理方法,收到消息会调用p.cfg.Listeners.*****(p, msg)方法
go p.queueHandler()
维护发送队列,从outputQueue通道读取放到sendQueue通道
go p.outHandler()
此方法负责从sendQueue通道读取消息,然后发送消息p.writeMessage(msg.msg, msg.encoding)
go p.pingHandler()
定时发送ping消息到outputQueue通道
本文作者:architect.bian,欢迎收藏,转载请保留原文地址并保留版权声明!谢谢~
还没完!往下看!!!