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

继续上一章节

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
}

猜你喜欢

转载自blog.csdn.net/luoye4321/article/details/83659225