当前位置:网站首页>Rust P2P网络应用实战-1 P2P网络核心概念及Ping程序
Rust P2P网络应用实战-1 P2P网络核心概念及Ping程序
2022-07-29 15:26:00 【InfoQ】
本系列文章首先研究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-learn
Created 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();
// 基于密钥对的公钥,生成节点唯一标识peerId
let 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 pingmaster:libp2p-learn Justin$ cargo run --bin ping
Compiling libp2p-learn v0.1.0 (/Users/Justin/workspace_rust_exercise/network-study/p2p/libp2p-learn)
Finished dev [unoptimized + debuginfo] target(s) in 8.65s
Running `target/debug/ping`
节点ID: 12D3KooWR7H9SwB2yiFBKvzcVGFdpeKmuFG9qDTBTvuuuDarASST
本地监听地址: /ip4/127.0.0.1/tcp/58645可以看到已经打印出PeerId和监听地址。
打开另一个终端,运行:
cargo run --bin ping /ip4/127.0.0.1/tcp/58645master:libp2p-learn Justin$ cargo run --bin ping /ip4/127.0.0.1/tcp/58645
Finished dev [unoptimized + debuginfo] target(s) in 0.36s
Running `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聊天程序。
边栏推荐
猜你喜欢
随机推荐
数字赋能机械制造业,供应链协同管理系统解决方案助力企业供应链再升级
linux 安装mysql8.0 超详细教程(实战多次)
You need to know about the digital transformation of eight guiding principles
MySQL数据库安装配置保姆级教程(以8.0.29为例)有手就行
详解微处理器CPU的系统结构
Floating point memory storage problem
苹果涉险过关,全靠iPhone 13
一文读懂Elephant Swap,为何为ePLATO带来如此高的溢价?
Google Earth Engine APP——一键实现底图添加和时序的添加和正反序的结合
泰芯TXW8301打造新一代8路无线监控NVR套装解决方案
Impala时间函数总结
Compose要是不 `remember`,相关功能就实现不了了吗?
我把小程序搬到了自有App中,开发效率提升了5倍
风格迁移篇----艺术风格转换的内容与风格解构
中国大学慕课mooc答题/自动播放脚本(domooc)使用教程
双非渣渣的上岸之路!备战 60 天,三战滴滴侥幸收获 Offer
BGP联邦实验
小米法务部:成功打击一处伪造Redmi蓝牙耳机窝点,查扣假冒伪劣产品2032个
VMware 16.1软件安装包下载及安装教程
DevOps的未来趋势









