Libp2p学习01一个简单的聊天服务

说明

本人是刚学 libp2p, 这些博客 不能当作是教程或者是引导
也许会有大量错误,欢迎大佬指导。

此博客源码 imjoel/go-libp2p-learn

搭建一个简单的穿透服务

搭建穿透服务一共需要3步,

  1. 生成一个节点ID
  2. 创建一个 Host
  3. 等待连接

1. 生成节点ID 不用多说,github.com/libp2p/go-libp2p-examples 上有示例, 下面是我将目标代码整合成了一个方法

import (
	crand "crypto/rand"
	"github.com/libp2p/go-libp2p-core/crypto"
	"io"
	mrand "math/rand"
)

func generateIdentity(seed int64) (identity crypto.PrivKey, err error) {
	var r io.Reader
	if seed == 0 {
		r = crand.Reader
	} else {
		r = mrand.New(mrand.NewSource(seed))
	}
	identity, _, err = crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, r)
	return identity, err
}

2. 要创建一个 Host 很简单,如果要创建一个 relay host 只需要指定 OptActiveOptHop 选项即可. 下面是我抽出来的创建 relay host 的函数

import (
	"context"
	"fmt"
	"github.com/libp2p/go-libp2p"
	circuit "github.com/libp2p/go-libp2p-circuit"
	"github.com/libp2p/go-libp2p-core/crypto"
	"github.com/libp2p/go-libp2p-core/host"
	"log"
)

func makeRelayHost(port int, hostAddress string,
	identity crypto.PrivKey, insecure bool) (host.Host, error) {
	opts := []libp2p.Option{
		libp2p.ListenAddrStrings(fmt.Sprintf("/ip4/%s/tcp/%d", hostAddress, port)),
		libp2p.Identity(identity),
		libp2p.EnableRelay(circuit.OptActive, circuit.OptHop),
	}
	if insecure {
		opts = append(opts, libp2p.NoSecurity)
		log.Println("[WARN] Insecure relay")
	}
	return libp2p.New(context.Background(), opts...)
}

3. 等待连接

创建一个简单的 relay server 可以参考 gitee.com/imjoel/go-libp2p-learn 中的示例代码

简单的聊天客户端

聊天客户端与穿透连接伪代码如下:

// 穿透服务的地址
var relayAddress string
// 同样连接到穿透服务的,朋友的节点ID
var targetPeerID string

// 创建一个 host
var myHost = new(host.Host)
// 连接到穿透服务
connectRelay(myHost, relayAddress)

if targetPeerID != "" {
    // 主动连接朋友
    connectFriend(myHost, targetPeerID)
} else {
    // 等待朋友连接我
    myHost.SetStreamHandler("/chat", func(){})
}

1. 创建 host

唯一需要注意的是该host 不能配置为 DisableRelay(), 至少需要 OptDiscovery 选项

import (
	"context"
	"github.com/libp2p/go-libp2p"
	circuit "github.com/libp2p/go-libp2p-circuit"
	"github.com/libp2p/go-libp2p-core/crypto"
	"github.com/libp2p/go-libp2p-core/host"
	"log"
)

func makeHost(identity crypto.PrivKey, insecure bool) (host.Host, error) {
	opts := []libp2p.Option{
		libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"),
		libp2p.Identity(identity),
		libp2p.EnableRelay(circuit.OptDiscovery),
	}
	if insecure {
		opts = append(opts, libp2p.NoSecurity)
		log.Println("[WARN] Insecure relay")
	}
	return libp2p.New(context.Background(), opts...)
}

2. 连接 relay

import (
	"context"
	"fmt"
	"github.com/libp2p/go-libp2p-core/host"
	"github.com/libp2p/go-libp2p-core/peer"
	ma "github.com/multiformats/go-multiaddr"
)

func connectRelay(h host.Host, relay string) error {
	relayAddr, err := ma.NewMultiaddr(relay)
	if err != nil {
		return err
	}
	pid, err := relayAddr.ValueForProtocol(ma.P_P2P)
	if err != nil {
		return err
	}
	relayPeerID, err := peer.IDB58Decode(pid)
	if err != nil {
		return err
	}

	relayPeerAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/p2p/%s", pid))
	relayAddress := relayAddr.Decapsulate(relayPeerAddr)

	peerInfo := peer.AddrInfo{
		ID:    relayPeerID,
		Addrs: []ma.Multiaddr{relayAddress},
	}
	return h.Connect(context.Background(), peerInfo)
}

3. 等待或主动发起聊天

参考示例代码 gitee.com/imjoel/go-libp2p-learn

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值