【libp2p——examples——relay分析】

1.例子简介

这个项目演示了使用Go中的libp2p库建立一个基于中继的点对点通信。它的特点是创建不可访问的libp2p主机,并通过中继节点促进它们的通信。

  • 创建两个“不可达”的libp2p主机。
  • 建立中继节点,使这些主机之间能够通信。

2. 步骤

  1. 存在两个不能直接存在的节点Node1,Node2(并且这两个节点接受来自中继节点的入站连接)
  2. 存在一个中继节点Relay
  3. Node1和Node2应该都可以连接到中继节点Relay,并将其加入到自己的地址簿
  4. Node2需要向Relay预定一个端口用来转发自己的消息
  5. Node1通过realy新建一个连接地址/p2p/relayAddress/p2p-circuit/p2p/targetAddress
  6. Node1尝试Connect Node2,成功后会将其加入到targetAddress加入到自己的地址簿
  7. 可以直接用Node2的ID和协议进行通讯

3. 代码分析

删除了一部分错误处理,使代码看起来更加简洁

func run(){
	// 创建一个在NAT后的节点1
	unreachable1, err := libp2p.New(
		libp2p.NoListenAddrs,
		// 启动中继功能是一个默认选项,但是我们在之前的NoListenAddrs覆盖了它,所以需要再次显式调用
		// 该选项仅将libp2p配置为接受来自中继的入站连接,并在远程对等体请求时进行出站连接。
		libp2p.EnableRelay(),
	)
	// 创建一个在NAT后的节点2
	unreachable2, err := libp2p.New(
		libp2p.NoListenAddrs,
		libp2p.EnableRelay(),
	)
	// 构建一个连接节点2的地址
	unreachable2info := peer.AddrInfo{
		ID:    unreachable2.ID(),
		Addrs: unreachable2.Addrs(),
	}
	err = unreachable1.Connect(context.Background(), unreachable2info)
	if err != nil {
		log.Printf("This is normal because NAT2 does not listen to addresses")
		return
	}
	// 正如我们所怀疑的那样,我们无法在无法到达的主机之间直接拨号
	// 创建一个主机作为中间人,代表我们传递消息
	relay1, err := libp2p.New()
	// 配置主机以提供电路中继服务。任何可以在网络(或互联网)中直接拨号的主机都可以提供电路中继服务,这不仅仅是“专用”中继服务的工作。在电路继电器v2(我们在这里使用!)中,它的速率是有限的,因此任何节点都可以安全地提供此服务
	_, err = relay.New(relay1)
	// 获得中继节点的连接地址
	relay1info := peer.AddrInfo{
		ID:    relay1.ID(),
		Addrs: relay1.Addrs(),
	}
	// 将unreachable1和unreachable2都连接到relay1
	if err := unreachable1.Connect(context.Background(), relay1info); err != nil {
		log.Printf("Failed to connect unreachable1 and relay1: %v", err)
		return
	}
	if err := unreachable2.Connect(context.Background(), relay1info); err != nil {
		log.Printf("Failed to connect unreachable2 and relay1: %v", err)
		return
	}
	// 现在为节点2设置流处理器
	unreachable2.SetStreamHandler("/customprotocol", func(s network.Stream) {
		log.Println("Awesome! We're now communicating via the relay!")
		// End the example
		s.Close()
	})
	// 节点2向中继节点relay1预留一个槽位,以便后续中继节点转发需要发送到node2的请求
	// 但我们还没告诉relay1如何识别node2的请求
	_, err = client.Reserve(context.Background(), unreachable2, relay1info)
	// 为node2创建一个新的地址
	relayaddr, err := ma.NewMultiaddr("/p2p/" + relay1info.ID.String() + "/p2p-circuit/p2p/" + unreachable2.ID().String())
	//由于我们刚刚尝试拨号失败,拨号系统将默认阻止我们如此迅速地重新拨号。既然我们知道我们在做什么,我们可以使用这个丑陋的hack(它在我们的TODO列表中,使它更简洁)来告诉拨号器“不,没关系,让我们再试一次”。
	// 清理上一次的拨号失败记录,因为拨号系统会
	unreachable1.Network().(*swarm.Swarm).Backoff().Clear(unreachable2.ID())
	// 通过中继地址打开到先前不可达主机的连接(relayaddr这是节点2的新地址,这是经过中继relay1的地址)
	unreachable2relayinfo := peer.AddrInfo{
		ID:    unreachable2.ID(),
		Addrs: []ma.Multiaddr{relayaddr},
	}
	// 拨号成功后会将其加入到自己的地址库
	if err := unreachable1.Connect(context.Background(), unreachable2relayinfo); err != nil {
		log.Printf("Unexpected error here. Failed to connect unreachable1 and unreachable2: %v", err)
		return
	}
	log.Println("Yep, that worked!")
	//因为我们没有到目标节点的直接连接——我们有一个中继连接——连接被标记为瞬态。由于中继限制了可以通过中继连接交换的数据量,因此应用程序需要显式地选择使用中继连接。一般来说,只有在带宽要求较低的情况下,我们才应该这样做,并且当中继连接被直接(holepched)连接取代时,我们很高兴连接被终止。
	// 节点1尝试连接到节点2的customprotocol的协议上
	s, err := unreachable1.NewStream(network.WithUseTransient(context.Background(), "customprotocol"), unreachable2.ID(), "/customprotocol")
	s.Read(make([]byte, 1))
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/886766.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Pikachu-Cross-Site Scripting-xss盲打

xss盲打,不是一种漏洞类型,而是一个攻击场景;在前端、或者在当前页面是看不到攻击结果;而是在后端、在别的页面才看到结果。 登陆后台,查看结果;

神经网络激活函数之前的加权求和 | 矩阵相乘运算法则(清晰版)

1. 神经网络中进行加权求和为什么要将w矩阵进行转置? 下面以一个简单的神经网络作为举例: 我们要将输入特征与W进行加权求和,想要的是下面这种结果: 但是根据矩阵相乘的运算法则: 矩阵A的列数(column&am…

CTF刷题buuctf

[WUSTCTF2020]颜值成绩查询 拿到相关题目,其实根据功能和参数分析。需要传入一个学号然后进行针对于对应的学号进行一个查询,很可能就会存在sql注入。 其实这道题最难的点,在于过滤了空格,因此我们使用 /**/来过滤空格的限制。…

低功耗4G模组Air780E之串口通信篇

你对低功耗4G模组Air780E有多少了解? 今天我们来讲解低功耗4G模组Air780E的串口通信的基本用法,小伙伴们,学起来吧! 一、硬件准备 780E开发板一套,包括天线、USB数据线。 USB转TTL工具或线(例如ch340、…

【mmengine】配置器(config)(入门)读取与使用

一、 介绍 MMEngine 实现了抽象的配置类(Config),为用户提供统一的配置访问接口。 配置类能够支持不同格式的配置文件,包括 python,json,yaml,用户可以根据需求选择自己偏好的格式。 配置类提供…

一站式大语言模型API调用:快速上手教程

智匠MindCraft是一个强大的AI工具及开发平台,支持多种大语言模型和多模态AI模型。本文将详细介绍如何通过API调用智匠MindCraft中的大语言模型,帮助开发者快速上手。 注册与登录 访问智匠MindCraft官网,注册并登录账号。 进入开发者平台&…

Oracle SQL语句没有过滤条件,究竟是否会走索引??

答案是:可能走索引也可能不走索引,具体要看列的值可不可为null,Oracle不会为所有列的nullable属性都为Y的sql语句走索引。 例子: create table t as select * from dba_objects; CREATE INDEX ix_t_name ON t(object_id, objec…

[VULFOCUS刷题]tomcat-pass-getshell 弱口令

tomcat-pass-getshell 弱口令 启动容器,打开网站 点开manageapp,输入弱口令 tomcat/tomcat 之后在下面上传jsp大马,首先生成一个jsp马 这里我直接使用github别人生成好的 tennc/webshell: This is a webshell open source project (github.…

uniapp 知识点

自定义导航 在page.json navigationstyle":"custom"navigateTo传参 页面传参只能onLoad(option)里面拿 px和upx的关系 在750设计图中,1px1upx 路由 navigateBack返回上一页 重定向 其实就是把当前页面干掉了 公共组件和页面共同点 computed,watc…

java项目实现钉钉异常告警实时监控

最近有个小伙伴问我,我们的项目核心业务的地方总是有异常,虽然有打印日志,但不能立马通知我;所以今天我就教大家如何实现异常报警实时提醒 1.需要有钉钉 自己新建的企业用户 2.建一个群,需要有三人以上;…

AMD发布首个AI小语言模型:6900亿token、推测解码提速3.88倍

AMD发布了自己的首个小语言模型(SLM),名为“AMD-135M”。相比于越来越庞大的大语言模型(LLM),它体积小巧,更加灵活,更有针对性,非常适合私密性、专业性很强的企业部署。 AMD-135小模型隶属于Llama家族,有两…

用Arduino单片机读取PCF8591模数转换器的模拟量并转化为数字输出

PCF8591是一款单芯片,单电源和低功耗8位CMOS数据采集设备。博文[1]对该产品已有介绍,此处不再赘述。但该博文是使用NVIDIA Jetson nano运行python读取输入PCF8591的模拟量的,读取的结果显示在屏幕上,或输出模拟量点亮灯。NVIDIA J…

java将word转pdf

总结 建议使用aspose-words转pdf,poi的容易出问题还丑… poi的(多行的下边框就不对了) aspose-words的(基本和word一样) poi工具转换 <!-- 处理PDF --><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres…

Redis: 集群测试和集群原理

集群测试 1 ) SET/GET 命令 测试 set 和 get 因为其他命令也基本相似&#xff0c;我们在 101 节点上尝试连接 103 $ /usr/local/redis/bin/redis-cli -c -a 123456 -h 192.168.10.103 -p 6376我们在插入或读取一个 key的时候&#xff0c;会对这个key做一个hash运算&#xff0c…

【算法】---快速排序

参考 左神和神书算法导论. 学习前置 了解并实现过快速排序。 笔者曾经在数据结构篇写过快速排序&#xff0c;现在面向算法篇快排。 快速排序 输入数据所有排列是等概率的&#xff0c; 这种情况对于实际工程上不会总是成立。朴素快速排序对于特定的输入很糟糕&#xff0c; …

Redis入门第一步:认识Redis与快速安装配置

认识Redis与快速安装配置&#x1f343; Redis是什么&#x1f432; 1.Redis的背景&#x1f38d; Redis&#xff08;Remote Dictionary Server&#xff09;译为"远程字典服务"&#xff0c;它是一款基于内存实现的键值型 NoSQL 数据库&#xff0c; 通常也被称为数据结…

Python 从入门到实战33(使用MySQL)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;通过熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 上篇文章我们讨论了数据库编程接口操作的相关知识。今天我们将学习…

音视频入门

一个视频&#xff0c;一秒内普遍大于等于25帧。 入门知识&#xff1a; 1.帧&#xff0c;一张画面就是一帧。一个视频就是由许许多多帧组成的。 帧率&#xff0c;单位时间内帧的数量。单位&#xff1a;帧/秒 或 fps。 分类&#xff1a;I帧&#xff0c;P帧&#xff0c;B帧 I…

IP协议报文

一.IP协议报头结构 二.IP协议报头拆解 1.4位版本 实际上只有两个取值&#xff0c;分别是4和6&#xff0c;4代表的是IPv4&#xff0c;6代表的是IPv6。 2.4位首部长度 IP协议报头的长度也是边长的&#xff0c;单位是*4&#xff0c;这里表示的大小为0~15&#xff0c;当数值为1…

【PyTorch】生成对抗网络

生成对抗网络是什么 概念 Generative Adversarial Nets&#xff0c;简称GAN GAN&#xff1a;生成对抗网络 —— 一种可以生成特定分布数据的模型 《Generative Adversarial Nets》 Ian J Goodfellow-2014 GAN网络结构 Recent Progress on Generative Adversarial Networks …