欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

go语言代码实现区块链-P2P节点发现(二)

程序员文章站 2022-07-01 15:30:30
...

继续上一章节

Loop函数代码如下:

func(k *Kad) loop(){	
	log.Println("go loop...")	
	loop:
	for{
		select{
			case <-k.ticker.C:
				//定时检测node数量,如果小于N,执行节点发现
				go k.checkNodes()
			case n:=<-k.tc:
				//将距离随机几点最近的节点写入K桶
				go k.findNodes(true,n)
			case n:=<-k.sc:
				//将距离随机几点最近的节点写入远程节点的K桶
				go k.findNodes(false,n)			
			case <-k.closed:
				break loop
		}
	}
}

CheckNodes函数代码如下:

//检测当前正常连接的节点
func(k *Kad)checkNodes(){
	
	log.Println("start checkNodes...")
		
	currentNode:=k.nodes
	l:=len(currentNode)
	if l==0{
		//写入种子节点至Nodes中
		if !Besends{
			k.nodes=append(k.nodes,nil)	
		}
			
	} 
	var targetID NodeID
	if l<minNodes{
		
		log.Println("start findnode...")
		
		//节点查找
		rand.Read(targetID[:])
		node:=Node{Addr:k.currendNode.Addr,TargetID:targetID,}		
		k.tc<-node
	}else{
		for _,n:=range currentNode{
			info:=Msg_Beat0+k.currendNode.Addr //发送心跳消息
			Udpconn.WriteToUDP([]byte(info),n.Addr)
		}
		
		//5秒后判断是否回应
		time.Sleep(time.Duration(5)*time.Second)
		
		k.mutex_a.Lock()
		defer k.mutex_a.Unlock()
		
		for _,n:=range currentNode{
			if !k.askedCons(n.Nodeid){
				k.deleteNode(n)	
			}
		}
		
		l=len(k.nodes)
		if l==0{
			//写入种子节点至Nodes中
			if !Besends{
				k.nodes=append(k.nodes,nil)	
			}		
		}
		
		if l<minNodes{
			
			log.Println("start findnode...")
			
			rand.Read(targetID[:])
			k.tc<-Node{Addr:k.currendNode.Addr,TargetID:targetID,}
		}		
	}
}

检测节点的流程是首先判断已经连接的节点数量是否小于最小连接数,如果等于0,先将种子节点放入K桶,依次向K桶中的Node发送FindNode指令,依次获取距离随机节点更近的节点。

//计算节点和随机节点的异或距离
func(k *Kad)distance(node *Node,t NodeID)(uint8,*Node){
	ct:=EOR(k.currendNode.Nodeid,t)
	nt:=EOR(node.Nodeid,t)
	var i uint8
	for i=0;i<HashBits/8;i++{
		if nt[i]==ct[i]{
			continue
		}
		if nt[i]<ct[i]{
			node.index=i
			node.distance=nt[i]
			return i,node
		}else{
			break
		}
		
	}
	
	return 0,nil
}
//异或计算
func EOR(tnode,fnode NodeID)NodeID{
	var n NodeID
	for i:=0;i<HashBits/8;i++{
		n[i]=tnode[i]^fnode[i]
	}
	
	return n
}

 

相关标签: go 区块链 P2P