func (s *ConnManager) GetNetRate() metrics.Stats {
	return s.bandwidthTracker.GetBandwidthTotals()
}
GetNetRate get rateinfo
package manage
import (
	"context"
	"fmt"
	"sort"
	"strings"
	"sync"
	"time"
	"github.com/33cn/chain33/common/log/log15"
	p2pty "github.com/33cn/chain33/system/p2p/dht/types"
	"github.com/33cn/chain33/types"
	core "github.com/libp2p/go-libp2p-core"
	"github.com/libp2p/go-libp2p-core/metrics"
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	kb "github.com/libp2p/go-libp2p-kbucket"
	"github.com/multiformats/go-multiaddr"
)
var (
	log = log15.New("module", "p2p.connManage")
)
const (
	maxBounds    = 30  
	maxOutBounds = 15  
)
type ConnManager struct {
	ctx              context.Context
	neighborStore    sync.Map
	host             core.Host
	bandwidthTracker *metrics.BandwidthCounter
	routingTable     *kb.RoutingTable
	cfg              *p2pty.P2PSubConfig
}
func NewConnManager(ctx context.Context, host core.Host, rt *kb.RoutingTable, tracker *metrics.BandwidthCounter, cfg *p2pty.P2PSubConfig) *ConnManager {
	connM := &ConnManager{}
	connM.ctx = ctx
	connM.host = host
	connM.routingTable = rt
	connM.bandwidthTracker = tracker
	connM.cfg = cfg
	return connM
}
func (s *ConnManager) RateCalculate(ratebytes float64) string {
	kbytes := ratebytes / 1024
	rate := fmt.Sprintf("%.3f KB/s", kbytes)
	if kbytes/1024 > 0.1 {
		rate = fmt.Sprintf("%.3f MB/s", kbytes/1024)
	}
	return rate
}
func (s *ConnManager) BandTrackerByProtocol() *types.NetProtocolInfos {
	bandprotocols := s.bandwidthTracker.GetBandwidthByProtocol()
	var infos netprotocols
	for id, stat := range bandprotocols {
		if id == "" || stat.RateIn+stat.RateOut == 0 {
			continue
		}
		var info sortNetProtocols
		info.Protocol = string(id)
		info.Ratein = s.RateCalculate(stat.RateIn)
		info.Rateout = s.RateCalculate(stat.RateOut)
		info.Ratetotal = s.RateCalculate(stat.RateIn + stat.RateOut)
		infos = append(infos, &info)
	}
	sort.Sort(infos)  
	var netinfoArr []*types.ProtocolInfo
	for _, info := range infos {
		var protoinfo types.ProtocolInfo
		protoinfo.Ratetotal = info.Ratetotal
		protoinfo.Rateout = info.Rateout
		protoinfo.Ratein = info.Ratein
		protoinfo.Protocol = info.Protocol
		if strings.Contains(protoinfo.Ratetotal, "0.000") {
			continue
		}
		netinfoArr = append(netinfoArr, &protoinfo)
	}
	return &types.NetProtocolInfos{Protoinfo: netinfoArr}
}
func (s *ConnManager) MonitorAllPeers() {
	ticker1 := time.NewTicker(time.Minute)
	defer ticker1.Stop()
	ticker2 := time.NewTicker(time.Minute * 2)
	defer ticker2.Stop()
	ticker3 := time.NewTicker(time.Second * 5)
	defer ticker3.Stop()
	for {
		select {
		case <-s.ctx.Done():
			return
		case <-ticker1.C:
			s.printMonitorInfo()
		case <-ticker2.C:
			s.procConnections()
		case <-ticker3.C:
			s.procRoutingTable()
		}
	}
}
func (s *ConnManager) printMonitorInfo() {
	var LatencyInfo = fmt.Sprintln("--------------时延--------------------")
	peers := s.FetchConnPeers()
	bandByPeer := s.bandwidthTracker.GetBandwidthByPeer()
	var trackerInfo = fmt.Sprintln("------------BandTracker--------------")
	for _, pid := range peers {
		tduration := s.host.Peerstore().LatencyEWMA(pid)
		if tduration == 0 {
			continue
		}
		LatencyInfo += fmt.Sprintln("PeerID:", pid.Pretty(), "LatencyEWMA:", tduration)
		if stat, ok := bandByPeer[pid]; ok {
			trackerInfo += fmt.Sprintf("PeerID:%s,RateIn:%f bytes/s,RateOut:%f bytes/s,totalIn:%d bytes,totalOut:%d\n",
				pid,
				stat.RateIn,
				stat.RateOut,
				stat.TotalIn,
				stat.TotalOut)
		}
		log.Debug(LatencyInfo)
		insize, outsize := s.BoundSize()
		trackerInfo += fmt.Sprintln("peerstoreNum:", len(s.host.Peerstore().Peers()), ",conn num:", insize+outsize, "inbound num", insize, "outbound num", outsize,
			"dht size", s.routingTable.Size())
		trackerInfo += fmt.Sprintln("-------------------------------------")
		log.Debug(trackerInfo)
	}
}
func (s *ConnManager) procConnections() {
	_, outBoundSize := s.BoundSize()
	if outBoundSize > maxOutBounds || s.Size() > maxBounds {
		return
	}
	for _, seed := range s.cfg.Seeds {
		info, err := genAddrInfo(seed)
		if err != nil {
			panic(`invalid seeds format in config, use format of "/ip4/118.89.190.76/tcp/13803/p2p/16Uiu2HAmRao56AsxpobLBvbNfDttheQxnke9y1uWQRMWW7XaEdk5"`)
		}
		_ = s.host.Connect(context.Background(), *info)
	}
	for _, node := range s.cfg.BootStraps {
		info, err := genAddrInfo(node)
		if err != nil {
			panic(`invalid bootStraps format in config, use format of "/ip4/118.89.190.76/tcp/13803/p2p/16Uiu2HAmRao56AsxpobLBvbNfDttheQxnke9y1uWQRMWW7XaEdk5"`)
		}
		_ = s.host.Connect(context.Background(), *info)
	}
	if s.cfg.RelayEnable {
		for _, node := range s.cfg.RelayNodeAddr {
			info, err := genAddrInfo(node)
			if err != nil {
				panic(`invalid relayNodeAddr in config, use format of "/ip4/118.89.190.76/tcp/13803/p2p/16Uiu2HAmRao56AsxpobLBvbNfDttheQxnke9y1uWQRMWW7XaEdk5"`)
			}
			if len(s.host.Network().ConnsToPeer(info.ID)) == 0 {
				s.host.Connect(context.Background(), *info)
			}
		}
	}
}
func (s *ConnManager) procRoutingTable() {
	for _, pid := range s.routingTable.ListPeers() {
		if len(s.host.Network().ConnsToPeer(pid)) == 0 {
			s.routingTable.RemovePeer(pid)
		}
	}
	for _, pid := range s.host.Network().Peers() {
		_, _ = s.routingTable.TryAddPeer(pid, true, true)
	}
}
func genAddrInfo(addr string) (*peer.AddrInfo, error) {
	mAddr, err := multiaddr.NewMultiaddr(addr)
	if err != nil {
		return nil, err
	}
	return peer.AddrInfoFromP2pAddr(mAddr)
}
func (s *ConnManager) AddNeighbors(pr *peer.AddrInfo) {
	if pr == nil {
		return
	}
	s.neighborStore.Store(pr.ID.Pretty(), pr)
}
func (s *ConnManager) IsNeighbors(pid peer.ID) bool {
	_, ok := s.neighborStore.Load(pid.Pretty())
	return ok
}
func (s *ConnManager) Delete(pid peer.ID) {
	_ = s.host.Network().ClosePeer(pid)
	s.routingTable.RemovePeer(pid)
}
func (s *ConnManager) FetchNearestPeers(count int) []peer.ID {
	if s.routingTable == nil {
		return nil
	}
	return s.routingTable.NearestPeers(kb.ConvertPeerID(s.host.ID()), count)
}
func (s *ConnManager) Size() int {
	return len(s.host.Network().Conns())
}
func (s *ConnManager) FetchConnPeers() []peer.ID {
	var peers = make(map[string]peer.ID)
	var allconns conns
	for _, conn := range s.host.Network().Conns() {
		allconns = append(allconns, conn)
	}
	sort.Sort(allconns)
	for _, conn := range allconns {
		peers[conn.RemotePeer().Pretty()] = conn.RemotePeer()
		if len(peers) >= maxBounds {
			break
		}
	}
	return convertMapToArr(peers)
}
func convertMapToArr(in map[string]peer.ID) []peer.ID {
	var pids []peer.ID
	for _, id := range in {
		pids = append(pids, id)
	}
	return pids
}
func (s *ConnManager) CheckDirection(pid peer.ID) network.Direction {
	for _, conn := range s.host.Network().ConnsToPeer(pid) {
		return conn.Stat().Direction
	}
	return network.DirUnknown
}
func (s *ConnManager) OutBounds() map[peer.ID][]network.Conn {
	var peers = make(map[peer.ID][]network.Conn)
	for _, con := range s.host.Network().Conns() {
		if con.Stat().Direction == network.DirOutbound {
			peers[con.RemotePeer()] = append(peers[con.RemotePeer()], con)
		}
	}
	return peers
}
func (s *ConnManager) InBounds() map[peer.ID][]network.Conn {
	var peers = make(map[peer.ID][]network.Conn)
	for _, con := range s.host.Network().Conns() {
		if con.Stat().Direction == network.DirInbound {
			peers[con.RemotePeer()] = append(peers[con.RemotePeer()], con)
		}
	}
	return peers
}
func (s *ConnManager) BoundSize() (insize int, outsize int) {
	var outBounds = make(map[peer.ID][]network.Conn)
	var inBounds = make(map[peer.ID][]network.Conn)
	for _, con := range s.host.Network().Conns() {
		if con.Stat().Direction == network.DirOutbound {
			outBounds[con.RemotePeer()] = append(outBounds[con.RemotePeer()], con)
		}
		if con.Stat().Direction == network.DirInbound {
			inBounds[con.RemotePeer()] = append(inBounds[con.RemotePeer()], con)
		}
	}
	insize = len(inBounds)
	outsize = len(outBounds)
	return
}