本系列文章首先研究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到灯火阑珊

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

  1. 2-RabbitMQ核心概念及AMQP协议

    RabbitMQ核心概念及AMQP协议 [root@Centos ~]# rabbitmq-plugins list Configured: E = explicitly enabled; e = i ...

  2. Maven核心概念及Eclipse使用Maven

    Eclipse使用Maven 1).添加Maven 2).修改本地库 3).建立Maven项目 4).文件结构 5).关于web项目报错的解决 新建立的文件无web结构: 修改: 结果: Ps:此时还 ...

  3. Mycat概述、核心概念及linux安装、运行、登录

    概述 Mycat,是一个数据库中间件,使用java语言编写,在程序和数据库之间塞一个代理层.使得操作物理数据库对我们透明化,可以像操作mysql等数据库那样操作mycat. 特性: 可以当做一个Mys ...

  4. 普通用户的计算机接入运营商,运营商应对互联网P2P应用的策略-通信/网络-与非网...

    摘要 从P2P流量现状及运营商互联网络组织和运营模式入手.分析了P2P应用给运营商带来问题的原因,阐明了对于P2P应用的看法,并给出了P2P流量控制策略. 随着计算机网络的广泛应用和多媒体资源的丰富, ...

  5. 服务器和kad正在连接,P2P连不上kad网络怎么解决?P2P连不上kad网络的处理方法教程详解...

    今天小编的朋友问小编p2p没有连上kad网络怎么办,这问题让他们非常苦恼,为了让大家告别p2p没有连上kad网络怎么办的烦恼,所以小编写了有关解决这办法的教程,希望能帮助到大家. 1.右击-打开文件位 ...

  6. p2p显示kad能连接 服务器未连接,P2P连不上kad网络怎么办

    今天小编的朋友问小编p2p没有连上kad网络怎么办,这问题让他们非常苦恼,为了让大家告别p2p没有连上kad网络怎么办的烦恼,所以小编写了有关解决这办法的教程,希望能帮助到大家. 1.右击-打开文件位 ...

  7. Day1:计算机网络概述——基本concept、网络结构:网络边缘、网络核心、接入网络;多路复用

    文章目录 一 .计算机网络? 1.计算机网络简介 2.什么是Internet --组成细节的角度 3.什么是Internet--服务角度 4.什么是网络协议? 5.课后思考.(视频课后讨论题目: 二. ...

  8. 计算机网络p2p应用,[计算机网络-应用层] P2P应用

    首先我们要先来区分一下下面的几种体系结构: CS:Client/Server 客户-服务器结构 BS:Browser/Server  浏览器-服务器结构 P2P:Peer to Peer 对等结构 B ...

  9. 网络核心之分组交换与电路交换

    文章目录 网络核心 分组交换 1. 存储转发传输 2. 排队时延和分组丢失 3. 转发表和路由选择协议 电路交换(circuit switching) 电路交换网络的复用 分组交换与电路交换的分析 网 ...

最新文章

  1. 谷歌发布地图「时光机」:100年前,你家街道长啥样?
  2. U-BOOT下使用bootm引导内核方法
  3. 利用一个继电器来实现脚踏鼠标按钮
  4. C#中三种定时器对象的比较
  5. vue 多个click_vue中touch和click共存的解决方式
  6. java用继承编写宠物乐园_MoreThanJavaDay 5:面向对象进阶继承详解
  7. 移动IM开发指南2:心跳指令详解
  8. 数据库的使用你可能忽略了这些 (续)
  9. 锡山国土推行数据中心“在线变更”
  10. jaxb注解使用_使用JAXB的简介
  11. python 批量增加文件前缀_用python批量提取视频中的音频文件
  12. 如何使用此功能强大的工具将Wemo添加到Homekit
  13. 数据结构与算法之五直接选择排序
  14. 《python可以这样学》第一章
  15. Entity Resolution(实体解析)
  16. SQLServer2008----对数据分区
  17. 《LDA数学八卦》读后笔记
  18. elasticsearch安装教程
  19. 【华为2019年校园招聘】2019-5-8 软件题
  20. MyBatis实现一对一,一对多关联查询

热门文章

  1. 总结: 数组常用的方法
  2. 百度董事长兼CEO李彦宏创立《百度互联网》全球最大的中文搜索引擎
  3. 让1.6亿美元的公司导致破产被50万美元贱卖的无解的Python bug
  4. C语言笔记 · 输入函数(scanf(),getchar(),getche(),getch(),gets())
  5. 新浪微博 (sso package or sign error)
  6. ios:在XCode下混合编译C++/Objective-C
  7. 彻底删除软件,删除注册列表信息
  8. 指标类数据标准如何定义?
  9. Log4j simple example
  10. RIL.java【2】