p2p网络编程-3-案例实践:pubsub(代码片段)

文杰@ 文杰@     2023-01-07     112

关键词:

libp2p网络通信中还有一种方式就是PubSub模式,也称订阅发布的模式,官方给出了订阅发布模式的一个案例=> 聊天室

在此学习记录一下

官方代码地址:https://github.com/libp2p/go-libp2p/tree/master/examples/pubsub

一、效果演示

二、代码理解

2.1 总体框架

总的来说代码构成由这五个步骤:

1~2两步较为简单不再赘述, 下面几点分点描述

2.2 创建mDNS节点发现服务

注意,使用mDNS作为节点发现需要保证所有的节点在同一个局域网即节点发现的范围在同一个局域网下

// discoveryNotifee gets notified when we find a new peer via mDNS discovery
// 节点发现的通告结构体,继承Notifee
type discoveryNotifee struct 
	h host.Host


// HandlePeerFound connects to peers discovered via mDNS. Once they're connected,
// the PubSub system will automatically start interacting with them if they also
// support PubSub.
// 继承函数,节点发现后的处理函数:自动链接节点
func (n *discoveryNotifee) HandlePeerFound(pi peer.AddrInfo) 
	fmt.Printf("discovered new peer %s\\n", pi.ID.Pretty())
	err := n.h.Connect(context.Background(), pi)
	if err != nil 
		fmt.Printf("error connecting to peer %s: %s\\n", pi.ID.Pretty(), err)
	


// setupDiscovery creates an mDNS discovery service and attaches it to the libp2p Host.
// This lets us automatically discover peers on the same LAN and connect to them.
func setupDiscovery(ctx context.Context, h host.Host) error 
	// setup mDNS discovery to find local peers
	disc := mdns.NewMdnsService(h, DiscoveryServiceTag)

	n := discoveryNotifeeh: h
	disc.RegisterNotifee(&n)
	return nil

2.3 加入聊天房

每个节点通过订阅房间的统一topic实现PubSub

1.聊天房数据结构

与一个topic一一对应,可以通过ChatRoom.Publish在topic中发布消息,并且接收所有的消息到Messages的channel中。

type ChatRoom struct 
	// Messages is a channel of messages received from other peers in the chat room
	Messages chan *ChatMessage

	ctx   context.Context
	ps    *pubsub.PubSub
	topic *pubsub.Topic
	sub   *pubsub.Subscription

	roomName string
	self     peer.ID
	nick     string


// ChatMessage gets converted to/from JSON and sent in the body of pubsub messages.
type ChatMessage struct 
	Message    string
	SenderID   string
	SenderNick string


func (cr *ChatRoom) Publish(message string) error 
	m := ChatMessage
		Message:    message,
		SenderID:   cr.self.Pretty(),
		SenderNick: cr.nick,
	
	msgBytes, err := json.Marshal(m)
	if err != nil 
		return err
	
	return cr.topic.Publish(cr.ctx, msgBytes)

2.加入聊天房逻辑

分为三步,成功后返回一个新的ChatRoom实例

func JoinChatRoom(ctx context.Context, ps *pubsub.PubSub, selfID peer.ID, nickname string, roomName string) (*ChatRoom, error) 
	// join the pubsub topic
	topic, err := ps.Join(topicName(roomName))
	if err != nil 
		return nil, err
	

	// and subscribe to it
	sub, err := topic.Subscribe()
	if err != nil 
		return nil, err
	

	cr := &ChatRoom
		ctx:      ctx,
		ps:       ps,
		topic:    topic,
		sub:      sub,
		self:     selfID,
		nick:     nickname,
		roomName: roomName,
		Messages: make(chan *ChatMessage, ChatRoomBufSize),
	

	// start reading messages from the subscription in a loop
	go cr.readLoop()
	return cr, nil

发布和订阅较为直观,下面是循环读取:

3.循环读取消息内容

循环读取内容,并将被容加入到消息channel中

// readLoop pulls messages from the pubsub topic and pushes them onto the Messages channel.
func (cr *ChatRoom) readLoop() 
	for 
		// Next returns the next message in our subscription
		// 找到下一个消息
		msg, err := cr.sub.Next(cr.ctx)
		if err != nil 
			close(cr.Messages)
			return
		
		// only forward messages delivered by others
		// 只接收别人的消息
		if msg.ReceivedFrom == cr.self 
			continue
		
		// 反序列化
		cm := new(ChatMessage)
		err = json.Unmarshal(msg.Data, cm)
		if err != nil 
			continue
		
		// send valid messages onto the Messages channel
		// 把消息加入 Messages channel
		cr.Messages <- cm
	

4.获取当前topic所有连接者

func (cr *ChatRoom) ListPeers() []peer.ID 
  // ListPeers returns a list of peers we are connected to in the given topic.
	return cr.ps.ListPeers(topicName(cr.roomName))

对于UI部分不是重点,会使用即可

总体来说案例使用较为简单,可以快速上手!

觉得不错的话,请点赞关注呦~~你的关注就是博主的动力
关注公众号,查看更多go开发、密码学和区块链科研内容:

hadoop3-mapreducecovid-19案例实践(代码片段)

一、COVID-19案例上篇文章对MapReduce进行了介绍,并编写了WordCount经典案例的实现,本篇为继续加深MapReduce的用法,实践COVID-19新冠肺炎案例,下面是上篇文章的地址:https://blog.csdn.net/qq_43692950/article/details/12719512... 查看详情

hadoop3-mapreducecovid-19案例实践(代码片段)

一、COVID-19案例上篇文章对MapReduce进行了介绍,并编写了WordCount经典案例的实现,本篇为继续加深MapReduce的用法,实践COVID-19新冠肺炎案例,下面是上篇文章的地址:https://blog.csdn.net/qq_43692950/article/details/12719512... 查看详情

矩池云|神经网络图像分割:气胸x光片识别案例(代码片段)

在上一次肺炎X光片的预测中,我们通过神经网络来识别患者胸部的X光片,用于检测患者是否患有肺炎。这是一个典型的神经网络图像分类在医学领域中的运用。另外,神经网络的图像分割在医学领域中也有着很重要的用作。接下... 查看详情

markdown语法案例

#一级标题##二级标题###三级标题####四级标题#####五级标题######六级标题###无序列表-文本1-文本2-文本3###有序列表1.文本12.文本23.文本3###网络连接[百度](www.baidu.com) ##引用>一盏灯,一片昏黄;一简书,一杯淡茶。守着那一份... 查看详情

hadoop3-mapreduce分组介绍及案例实践(代码片段)

一、MapReduce分组上篇文章对MapReduce分区进行了介绍,通过分区规则控制不同的数据进到不同的reducetask中,而本篇文章讲的分组则是进到同一个reducetask中的数据的归类分组规则,下面是上篇文章的地址:https://blog.c... 查看详情

hadoop3-mapreduce分组介绍及案例实践(代码片段)

一、MapReduce分组上篇文章对MapReduce分区进行了介绍,通过分区规则控制不同的数据进到不同的reducetask中,而本篇文章讲的分组则是进到同一个reducetask中的数据的归类分组规则,下面是上篇文章的地址:https://blog.c... 查看详情

01html基础案例实践04

day04案例实践 html有五个部分构成: logo 导航栏 banner图 内容(文章内容,链接区) 页脚 案例代码(index4.html): 1<!DOCTYPEhtml>2<htmllang="en">3<head>4<metacharset="UTF-8">5<title>html案例</title& 查看详情

201991262019-2020-2《网络攻防实践》实践(代码片段)

目录论文实践FuzzFactory:Domain-SpecificFuzzingwithWaypoints部分翻译1简介2背景和动机2.1覆盖引导模糊化2.2一个激励人心的例子2.3航路点3fuzzfactory:一个特定于领域的FUZZING框架3.1领域特定反馈3.2航路点3.3组成域3.4领域特定模糊化算法4特定... 查看详情

sparkbug实践(包含的bug:classcastexception;connectexception;noclassdeffounderror;runtimeexceptio等。。。。)(代码片

文章目录环境问题一问题二问题三环境scala版本:2.11.8jdk版本:1.8spark版本:2.1.0hadoop版本:2.7.1ubuntu版本:18.04window版本:win10scala代码在windows端编程,ubuntu在虚拟机安装,scala,jdk& 查看详情

rdd编程初级实践(基于python)(代码片段)

RDD编程初级实践(基于python)1.实验目的2.实验环境3.实验数据3.1pyspark交互式编程(实验描述)3.2编写独立应用程序实现数据去重(实验描述)3.3编写独立应用程序实现求平均值问题(实验描述)3.4... 查看详情

3-3编程练习:jquery键盘事件案例(代码片段)

3-3编程练习完善下面的代码,在input框中输入内容的时候同样显示在下面的p标签中<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><title>习题</title></head><body><inputtype="text"v 查看详情

2020.3.6循环实践编程(数字翻转)(代码片段)

数字翻转#include<stdio.h>//循环实践intmain()intoldNumber,newNumber,digitNumber,iniValue;newNumber=0;printf("inputyournumber:");scanf("%d",&iniValue);oldNumber=iniValue;while(oldNumber!=0)digitNumber=oldNumber%10;newNumber=newNumber*10+digitNumber;oldNumber=oldNumber/10;printf("%dco... 查看详情

golang-爬虫案例实践(代码片段)

目录Golang-爬虫案例实践1.爬虫步骤2.正则表达式3.并发爬取美图Golang-爬虫案例实践1.爬虫步骤明确目标(确定在哪个网址搜索)爬(爬下数据)取(去掉没用的数据)处理数据(按具体业务去使用数据)2.正则表达式文档:https://s... 查看详情

中小研发团队架构实践之系列大纲

...做,你也能成为架构师第1章中小研发团队架构实践,附案例和代码  一、框架篇——工欲善其事,必先利其器  二、架构篇——思想提升  三、公共应用篇——业务与技术的结合  四、进阶篇——从架构到管理  五... 查看详情

免杀原理与实践

201753142020-3《网络对抗技术》Exp3免杀原理与实践Week5目录201753142020-3《网络对抗技术》Exp3免杀原理与实践Week5一、实践目标1、实践对象2、实践内容二、基础知识1、实践要求2、指令/参数3、预备知识三、实践步骤1、正确使用msf编... 查看详情

微服务实战:服务发现的可行方案以及实践案例

这是关于使用微服务架构创建应用系列的第四篇文章。第一篇介绍了微服务架构的模式,讨论了使用微服务架构的优缺点。第二和第三篇描述了微服务架构内部的通讯机制。这篇文章中,我们将会探讨服务发现相关问题。为什么... 查看详情

机器学习——深度神经网络实践(fcncnnbp)(代码片段)

目录系列文章目录一、CNN(卷积神经网络)与FCN(全连接网络)的异同1.相同点2.区别二、神经网络前向后向传播算法的优化迭代公式三、深度神经网络算法的应用1.人脸识别1.1数据导入1.2模型搭建与使用1.3结果与... 查看详情

jdk8函数式编程最佳实践(代码片段)

文章导航JDK8函数式编程最佳实践1.Lambda表达式的重要接口1.1新增的函数接口1.1无参数,无返回值类型接口1.2无参数,有返回值类型接口1.3有参数,也有返回值的类型接口2.方法引用2.1静态方法引用2.2实例方法引用2.3构... 查看详情