Rust P2P网络应用实战-1 P2P网络核心概念及Ping程序

article/2025/9/27 22:54:13

本系列文章首先研究P2P网络的核心概念,然后详细分析libp2p-rust库中的应用实例,为以后开发P2P网络应用程序打好基础。

P2P网络

P2P(Peer-to-Peer)是一种网络技术,可以在网络中不同的计算机上共享各种计算资源,如CPU、网络带宽和存储等。P2P技术应用最广泛的是在网络中共享文件以及区块链网络,它们不依赖中央服务器或中介来连接多个客户端,用户的计算机即是客户端也是服务器。

由于P2P网络是一种分布式系统,不会像中央服务器一样存在单点故障,因此容错性极强。

 

下面让我们来看一看P2P网络的核心概念:

传输协议

在P2P网络底层一般使用TCP/UDP传输层协议。由于P2P节点应用的多样性,在TCP/UDP传输层协议之上,会使用多种应用层协议,如:HTTP,gRPC及自定义协议等。为了有效利用资源,P2P网络会在一个连接上监听、解析多种协议,即多路复用技术:多个逻辑子流可以在同一个底层(TCP)连接上共存。可以查看yamux 库了解更多细节。

节点标识

P2P网络中的节点需要一个唯一的标识,以便其他节点能够找到它们。P2P网络中的节点使用公钥和私钥对(非对称公钥加密)与其他节点建立安全通信。在P2P网络中节点标识被称为PeerId,它是通过对节点公钥进行加密哈希得到的。

安全规则

密钥对和节点身份标识使节点之间能够体建立安全的、经过身份验证的通信通道。但这只是安全的一个方面,节点还需要根据业务逻辑实现授权框架,该框架建立一些规则:哪些节点可以执行哪种类型的操作等。

节点路由

P2P网络中的一个节点首先需要找到其他节点来进行通信。这是通过维护一个节点路由表来实现的。但是在P2P网络中,有成千上万个节点在动态变化(即节点的加入和离开),单个节点很难为网络中的所有节点维护一个完整、准确的路由表。所以节点路由表通常会由一系列路由节点维护。

消息

P2P网络中的节点可以向特定节点发送消息,也可以广播消息。使用发布/订阅模式,节点订阅感兴趣Topic,所有订阅该Topic的节点都能接收和发送消息。这种技术也通常用于将消息的内容传输到整个网络。

流多路复用

在P2P网络中,允许多个独立的“逻辑”流共享一个公共的P2P传输层。流多路复用有助于优化节点之间建立网络连接的开销。多路复用在后端服务开发中很常见,客户端可以与服务器建立底层网络连接,然后在底层网络连接上复用不同的流。

libp2p

自己编写P2P应用程序的网络层是一项庞大的工程,我们将使用底层p2p网络库—libp2p,在其上构建p2p应用程序会更加容易。libp2p是一个模块化的系统,支持三种编程语言:Rust、Go、JS。许多流行的项目中都使用libp2p做为P2P网络底层,如IPFS、 Filecoin、Polkadot和Substrate。

libp2p将P2P网络基本概念分解成了不同的模块,可以在不同的应用场景中组合使用。

我们先通过Ping这个简单的程序来熟悉一下libp2p的组件及如何使用libp2p开发点对点网络。

PING

这个例子非常简单,主要就是一个节点向另一个节点发送ping消息,然后等待另一个节点返回pong消息。

新建一个项目名叫:libp2p-learn

master:p2p Justin$ cargo new libp2p-learnCreated binary (application) `libp2p-learn` package
master:p2p Justin$ cd libp2p-learn/
master:libp2p-learn Justin$ code .

在Cargo.toml文件中加入libp2p和tokio依赖:

[dependencies]
libp2p = "0.46"
tokio = { version = "1.19", features = ["full"] }

然后在src/bin/目录下创建ping.rs文件:

use std::error::Error;use libp2p::{futures::StreamExt,identity,ping::{Ping, PingConfig},swarm::SwarmEvent,Multiaddr, PeerId, Swarm,
};#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {// 生成密钥对let key_pair = identity::Keypair::generate_ed25519();// 基于密钥对的公钥,生成节点唯一标识peerIdlet peer_id = PeerId::from(key_pair.public());println!("节点ID: {peer_id}");// 声明Ping网络行为let behaviour = Ping::new(PingConfig::new().with_keep_alive(true));// 传输let transport = libp2p::development_transport(key_pair).await?;// 网络管理模块let mut swarm = Swarm::new(transport, behaviour, peer_id);// 在节点随机开启一个端口监听swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;// 从命令行参数获取远程节点地址,进行链接。if let Some(remote_peer) = std::env::args().nth(1) {let remote_peer_multiaddr: Multiaddr = remote_peer.parse()?;swarm.dial(remote_peer_multiaddr)?;println!("链接远程节点: {remote_peer}");}loop {// 匹配网络事件match swarm.select_next_some().await {// 监听事件SwarmEvent::NewListenAddr { address, .. } => {println!("本地监听地址: {address}");}// 网络行为事件SwarmEvent::Behaviour(event) => println!("{:?}", event),_ => {}}}
}
  • 网络行为Behaviour:传输(transport)定义如何在网络中发送字节流,而网络行为定义发送什么样的字节流,在这里我们发送ping/pong消息。
  • 网络管理模块Swarm:用于管理节点之间的所有活跃连接和挂起连接,并管理所有已打开的子流状态。Swarm是通过传输、网络行为和节点PeerId来创建。
  • 节点地址:/ip4/0.0.0.0/tcp/0,表示在本机所有ip地址上,开一个随机的Tcp端口进行监听。

打开一个终端,运行:

cargo run --bin ping
master:libp2p-learn Justin$ cargo run --bin pingCompiling libp2p-learn v0.1.0 (/Users/Justin/workspace_rust_exercise/network-study/p2p/libp2p-learn)Finished dev [unoptimized + debuginfo] target(s) in 8.65sRunning `target/debug/ping`
节点ID: 12D3KooWR7H9SwB2yiFBKvzcVGFdpeKmuFG9qDTBTvuuuDarASST
本地监听地址: /ip4/127.0.0.1/tcp/58645

可以看到已经打印出PeerId和监听地址。

打开另一个终端,运行:

cargo run --bin ping /ip4/127.0.0.1/tcp/58645
master:libp2p-learn Justin$ cargo run --bin ping /ip4/127.0.0.1/tcp/58645Finished dev [unoptimized + debuginfo] target(s) in 0.36sRunning `target/debug/ping /ip4/127.0.0.1/tcp/58645`
节点ID: 12D3KooWCUFTHNMJrR1p8vkFEFFYm4J8iPA1Wh6x2Dya5qmU1xdL
链接远程节点: /ip4/127.0.0.1/tcp/58645
本地监听地址: /ip4/127.0.0.1/tcp/58727
Event { peer: PeerId("12D3KooWR7H9SwB2yiFBKvzcVGFdpeKmuFG9qDTBTvuuuDarASST"), result: Ok(Pong) }
Event { peer: PeerId("12D3KooWR7H9SwB2yiFBKvzcVGFdpeKmuFG9qDTBTvuuuDarASST"), result: Ok(Ping { rtt: 1.234008ms }) }

我们可以看到链接到刚刚的节点/ip4/127.0.0.1/tcp/58645成功,也收到了发送过来的ping/pong的消息。

下一篇文章我们将详细解析P2P聊天程序。


更多文章,请关注公众号:coding到灯火阑珊


http://chatgpt.dhexx.cn/article/YO7SQIkf.shtml

相关文章

区块链P2P网络协议演进过程

区块链是以加密机制、储存机制、共识机制等多种技术组成的分布式系统&#xff0c;可以在无中心服务器的情况下实现相互信任的点对点交易功能。区块链最大的特点是去中心化和分布式&#xff0c;区块链共识机制使得参与节点共同为系统提供服务&#xff0c;实现中心化系统中类似金…

【区块链实战】什么是 P2P 网络,区块链和 P2P 网络有什么关系

目录 一、简介 二、知识点 P2P 网络 区块链节点与 P2P 的关系 区块链节点功能分类 P2P 网络特征 三、什么是 P2P 网络&#xff0c;区块链式使用 P2P 网络做什么 1、P2P 网络概念 2、P2P 网络节点特征 3、P2P 与区块链 4、网络节点功能 一、简介 在白皮书中&#xf…

Peer to Peer ( P2P ) 综述

Peer to Peer ( P2P ) 综述 罗杰文 luojwics.ict.ac.cn 中科院计算技术研究所 2005-11-3 1 绪言 1.1 Peer-To-Peer 介绍 最近几年&#xff0c;对等计算 目前,在学术界、工业界对于P2P没有一个统一的定义&#xff0c;下面列举几个常用的定义供参考&#xff1a; 定义:1、Pe…

Ubuntu对分区扩容

Ubuntu对分区扩容 准备工具 1、U盘 2、准备好的内存空间 3、Ubuntu的镜像文件 4、清楚如何进入自己电脑的BIOS 扩容大致方向try Ubuntu 网络上的扩容方法大都是在自己的Ubuntu下使用GParted,对将要扩容的分区进行卸载&#xff0c;然后进行扩容&#xff0c;但是这样做有个前…

linux ubuntu 分区,查看Ubuntu分区列表方法

今天在Ubuntu修复Grub正好碰到了要展示分区列表看看 不然都不清楚哪个是哪个了。。 sudo fdisk -l 就是这个命令 ubuntuubuntu:~$ sudo fdisk -l Disk /dev/sda: 250.0 GB, 250059350016 bytes 255 heads, 63 sectors/track, 30401 cylinders Units cylinders of 16065 * 512 …

U盘安装ubuntu20.04 Linux系统分区方案 Invalid Partition Table

一、简介&#xff1a; 一般磁盘分区表有两种格式&#xff1a;MBR和GPT&#xff0c;目前主要的BIOS系统引导方式也有两种&#xff1a;传统的Legacy BIOS和新型的UEFI BIOS 如果主机BIOS系统引导方式采用传统的Legacy BIOS&#xff0c;那么安装ubuntu系统的磁盘分区表使用MBR格式…

Android布局

目录 1. Android的基础布局 2. LinearLayout 线性布局 3. RelativeLayout 4. 常用的控件 1. Android的基础布局 LinearLayout 线性布局 RelativeLayout 相对布局 TableLayout 表格布局 FrameLayout 帧布局&#xff08;框架布局&#xff09; ConstrantLayout 约束布局 &…

安卓布局简单归纳

安卓布局 1.线性布局LinearLayout 2.表格布局TableLayout以及网格布局GridLayout 3.帧布局FrameLayout 4.相对布局RelativeLayout 5.Android2.0已经过时的绝对布局AbsoluteLayout 这里仅谈xml的实现、不涉及java实现 布局管理器及组件的常用共有属性&#xff1a; 属性作用and…

安卓layout布局三等分

关于android LinearLayout的比例布局&#xff0c;主要有以下三个属性需要设置&#xff1a; 1&#xff0c;android:layout_width&#xff0c;android:layout_height,android:layout_weight三个值 2&#xff0c;当为水平布局时&#xff0c;android:layout_height“0dp",当为…

安卓APP(3)——安卓布局控件

嵌入式之路&#xff0c;贵在日常点滴 ---阿杰在线送代码 目录 一、布局的种类 二、布局和页面的关系 三、显示一张美女图 控件的宽度和高度 四、布局背景颜色&#xff0c;背景图&#xff0c;显示两个美女 关于控件ID 五、常用布局之相对布局 RelativeLayout中子控件常…

安卓的相对布局与线性布局

一、安卓布局的种类 Android共有七大基本布局。 分别是&#xff1a;线性布局LinearLayout、表格布局TableLayout、相对布局RelativeLayout、帧布局FrameLayout、绝对布局AbsoluteLayout、网格布局GridLayout。约束布局ConstraintLayout。 其中&#xff0c;表格布局是线性布局的…

Android:布局

Android&#xff1a;布局 LinearLayoutRelativeLayoutFrameLayoutTableLayoutGridLayoutConstraintLayout LinearLayout <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_height"match_parent"android:layout_…

安卓六大布局之 线性布局(LinearLayout)

Android的界面是有布局和组件协同完成的&#xff0c;布局好比是建筑里的框架&#xff0c;而组件则相当于建筑里的砖瓦。组件按照布局的要求依次排列&#xff0c;就组成了用户所看见的界面。 Android的六大布局分别是 LinearLayout&#xff08;线性布局&#xff09;RelativeLayo…

Android-布局管理器

线性布局(Linearlayout) 属性 orientation 布局管理器内组件的排列方式(horizontal&#xff08;水平&#xff09;和vertical&#xff08;垂直&#xff09;&#xff0c;默认值为 horizontal.) layout_weight 权重 用于设置组件占父容器剩余空间的比例 la…

android 布局

android学习笔记&#xff08;一 android布局学习&#xff09; 转自http://blog.sina.com.cn/s/blog_61c62a960100ev3q.html (2009-09-20 20:50:44) 转载 标签&#xff1a; it 分类&#xff1a;android 最近痴迷上了android &#xff0c; 因为有java 语言的基础学起来自己感觉很…

安卓六大布局介绍

安卓六大布局 布局的介绍安卓六大布局 布局的介绍 用户使用安卓看到的应用界面&#xff0c;是通过布局和组件构成的&#xff0c;组件根据布局的格式排列&#xff0c;形成用户所看到的界面。 安卓六大布局 线性布局方式&#xff08;LinearLayout&#xff09; 按照垂直或者水平…

安卓线性布局

安卓线性布局 &#xff08;一&#xff09;界面与布局1、界面2、布局&#xff08;1&#xff09;UI容器&#xff08;2&#xff09;UI控件 (Control)&#xff08;3&#xff09;两种方式声明布局 &#xff08;二&#xff09;线性布局&#xff08;1&#xff09;常用属性 &#xff08…

安卓的常用布局看一篇就够了

目录 1-1 布局通用的属性 1-2 线性布局&#xff08;LinearLayout&#xff09; 1、常见属性&#xff1a; 2、线性布局的例子&#xff1a; 1-3 相对布局&#xff08;RelativeLayout&#xff09; 1、常见属性&#xff1a; 2、 相对布局的例子&#xff1a; 1-4 帧布局&a…

android布局技巧:创建高效布局

Android UI工具包提供了一些布局管理器&#xff0c;它们使用起来相当容易&#xff0c;而且&#xff0c;大多数的时候&#xff0c;你只需要使用它们最基本的特征来实现UI。 执着于基本特征的使用对于创建UI来说&#xff0c;往往不是最高效的。一个常见的例子就是滥用LinearLayo…