【go-libp2p学习笔记】使用go-libp2p搭建中转服务器(circuit relay server)

本文介绍如何使用Go-libp2p库搭建NAT穿透的中转服务器(circuit relay server),实现两个处于NAT后的节点通过该服务器建立P2P连接。文章详细解释了libp2p的基本概念,如libp2p节点、Multiaddr等,并提供了一个具体的代码实例,展示了客户端和服务端的核心代码。

使用go-libp2p搭建中转服务器(circuit relay server)

libp2p算是一个蛮新的库,提供了非常强大的p2p节点发现/连接/通信能力。IPFS的基石。
中文网上的技术教程比较少,所以抛砖引玉开一点坑来体验一下!

这篇博客本质上就是用libp2p做一个NAT打洞建立p2p的实现,不过过程中能够学到很多libp2p的概念,当然用libp2p做也应该有不少好处有待进一步研究。

代码基于:
https://github.com/libp2p/go-libp2p/tree/master/examples
和一些外网教程

复现本篇博客的技术基础

  1. 基础的Go语言能力(我也不是很懂,GO能学的太多了,超过我上一篇博客的内容基本上都不会)
  2. Go version>=1.19(libp2p的要求)
  3. NAT与NAT打洞相关概念
  4. 一台具有公网IP的服务器
  5. 你自己的电脑

1. 了解一些libp2p基础概念

  1. libp2p-node, 或说Host, 中文名节点, 不是指网络中的一个主机, 而是指的网络连接中的一个独立端点, 一个独立的应用程序, 一台电脑/服务器上面可以配置多个host. 在go-libp2pexample中, 很多测试都是在同一个电脑上运行的.
  2. Multiaddr, libp2p网络传输层的协议中, 用一个Multiaddr概念来统领两个节点之间的多种连接方式. 从而对更高层的应用隐藏底部的具体连接协议.

2. 原理

两个藏在NAT或防火墙后面的host:A, B; 一个可以被公网访问到的(比如说具有公网IP)host:R
这里A是等待被访问的host, B是要去访问A的host
首先A需要先去连接中转服务器R, 进行一个预定Reservation, 这样A和R的双向通路就打开了.
接下来B向R发出连接到A的请求, R帮助B与A建立连接
20221101101037

3. 代码核心语句解释

代码主要分为两个程序: 客户端服务端/中转服务器

中转服务器的核心代码:
	relay1, err := libp2p.New()
 	_, err = relay.New(relay1)

    log.Printf("relay1Info ID: %v Addrs: %v",relay1.ID(), relay1.Addrs())

就这么短, 很简单.
第一句话创建一个新的host,
第二句话在host上配置中转服务器
第三句话将host的ID和地址打印出来, 这里我们手动复制传给A和B

客户端的核心代码:

客户端也分为两个部分, 等待被连接的Ahost, 和去连接A的Bhost.
这里我们直接用是否输入了被连接的Ahost的ID作为本客户端是A还是B的判断条件.
等待被连接的Ahost

	unreachableNode, err := libp2p.New(
		libp2p.NoListenAddrs,
		// Usually EnableRelay() is not required as it is enabled by default
		// but NoListenAddrs overrides this, so we're adding it in explictly again.
		libp2p.EnableRelay(),
	)


    relayServerID := "12D3KooWHwN52aYe18Wa6meTcLtrQ6y7jKXaQ85zf2snxsUWPA9B"
	ms1, _ := ma.NewMultiaddr(fmt.Sprintf("/ip4/43.143.xxx.xxx/tcp/38403/p2p/%v", relayServerID))
	relay1info, err := peer.AddrInfoFromP2pAddr(ms1)
    if err := unreachableNode.Connect(context.Background(), *relay1info); err != nil {
   
   
       log.Printf("Failed to connect unreachable1 and relay1: %v", err)
       return
	}
 	_, err = client.Reserve(context.Background(), unreachableNode, *relay1info)
    

	// Now, to test the communication, let's set up a protocol handler on unreachable2
	unreachableNode.SetStreamHandler("/chatStream", func(s network.Stream) {
   
   
		log.Println("Awesome! We're now communicating via the relay!")
		log.
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值