Rust NOSTR协议中继池库nostr-relay-pool的使用:实现高效分布式消息中继与网络连接管理
Rust NOSTR协议中继池库nostr-relay-pool的使用:实现高效分布式消息中继与网络连接管理
功能标志
以下是可用的crate功能标志:
功能 | 默认 | 描述 |
---|---|---|
tor |
否 | 启用嵌入式tor客户端支持 |
状态
该库处于ALPHA状态,已实现的功能通常可以工作,但API将会以不兼容的方式发生变化。
捐赠
rust-nostr
是免费和开源的。这意味着我们不会通过出售它来获得任何收入。相反,我们依赖于您的财务支持。如果您积极使用任何rust-nostr
库/软件/服务,请考虑捐赠。
许可证
该项目采用MIT软件许可证分发 - 详情请参阅LICENSE文件
安装
在项目目录中运行以下Cargo命令:
cargo add nostr-relay-pool
或者将以下行添加到您的Cargo.toml中:
nostr-relay-pool = "0.43.0"
示例代码
以下是使用nostr-relay-pool库的完整示例:
use nostr_relay_pool::RelayPool;
use nostr::prelude::*;
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() -> Result<()> {
// 创建密钥对
let keys = Keys::generate();
// 初始化中继池
let relay_pool = RelayPool::new();
// 添加中继URL
relay_pool.add_relay("wss://relay.damus.io", None).await?;
relay_pool.add_relay("wss://nostr.wine", None).await?;
// 连接到所有中继
relay_pool.connect().await;
// 创建事件
let event = EventBuilder::new_text_note("Hello from nostr-relay-pool!", &[])
.to_event(&keys)?;
// 发送事件到所有中继
relay_pool.send_event(event).await?;
// 订阅事件
let subscription = Filter::new()
.kind(Kind::TextNote)
.limit(10);
relay_pool.subscribe("my-subscription", vec![subscription]).await;
// 处理接收到的消息
while let Ok(notification) = relay_pool.notifications().recv().await {
match notification {
RelayPoolNotification::Event(_sub_id, event) => {
println!("Received event: {:?}", event);
},
RelayPoolNotification::Message(_relay_url, message) => {
println!("Received message: {:?}", message);
},
_ => {}
}
}
// 等待一段时间
sleep(Duration::from_secs(30)).await;
// 断开所有中继连接
relay_pool.disconnect().await?;
Ok(())
}
这个示例展示了:
- 创建密钥对
- 初始化中继池
- 添加多个中继服务器
- 连接到所有中继
- 创建并发送事件
- 订阅和接收事件
- 处理不同类型的通知
- 断开连接
完整示例代码
以下是基于上述内容的完整示例demo:
// 引入必要的库
use nostr_relay_pool::RelayPool;
use nostr::prelude::*;
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() -> Result<()> {
// 1. 创建密钥对 - 用于签名事件
let keys = Keys::generate();
println!("生成公钥: {}", keys.public_key());
// 2. 初始化中继池
let relay_pool = RelayPool::new();
// 3. 添加多个中继服务器
let relays = vec![
"wss://relay.damus.io",
"wss://nostr.wine",
"wss://nos.lol"
];
for relay in relays {
match relay_pool.add_relay(relay, None).await {
Ok(_) => println!("成功添加中继: {}", relay),
Err(e) => eprintln!("添加中继失败 ({}): {}", relay, e),
}
}
// 4. 连接到所有中继
println!("连接中继中...");
relay_pool.connect().await;
// 5. 创建并发送文本事件
println!("准备发送事件...");
let event = EventBuilder::new_text_note("Hello from nostr-relay-pool demo!", &[])
.to_event(&keys)?;
match relay_pool.send_event(event).await {
Ok(_) => println!("事件发送成功"),
Err(e) => eprintln!("事件发送失败: {}", e),
}
// 6. 订阅文本事件
println!("订阅文本事件...");
let subscription = Filter::new()
.kind(Kind::TextNote)
.limit(10);
relay_pool.subscribe("text-note-subscription", vec![subscription]).await;
// 7. 处理接收到的消息
println!("开始监听事件...");
tokio::spawn(async move {
while let Ok(notification) = relay_pool.notifications().recv().await {
match notification {
RelayPoolNotification::Event(sub_id, event) => {
println!("[{}] 收到事件 ({}): {}",
sub_id,
event.kind,
event.content
);
},
RelayPoolNotification::Message(relay_url, message) => {
println!("来自 {} 的消息: {:?}", relay_url, message);
},
RelayPoolNotification::RelayStatus(url, status) => {
println!("中继状态变化: {} -> {:?}", url, status);
},
_ => {}
}
}
});
// 8. 等待一段时间让程序运行
println!("运行30秒...");
sleep(Duration::from_secs(30)).await;
// 9. 断开所有中继连接
println!("断开中继连接...");
relay_pool.disconnect().await?;
println!("程序结束");
Ok(())
}
这个完整示例扩展了原始示例,增加了:
- 更多错误处理和日志输出
- 添加了多个中继服务器的循环处理
- 增加了对中继状态变化的监听
- 使用tokio::spawn来异步处理通知
- 更详细的运行状态输出
注意:该库仍处于ALPHA阶段,API可能会发生变化。使用时请参考最新文档。
1 回复
Rust NOSTR协议中继池库nostr-relay-pool的使用指南
介绍
nostr-relay-pool是一个用于NOSTR协议的Rust库,它提供了高效管理多个中继服务器连接的能力。NOSTR(Notes and Other Stuff Transmitted by Relays)是一个简单的开放协议,用于去中心化社交网络,而中继服务器是该协议的核心组件。
这个库的主要功能包括:
- 管理多个中继连接池
- 自动重连机制
- 消息订阅和发布
- 高效的事件过滤
安装
在Cargo.toml中添加依赖:
[dependencies]
nostr-relay-pool = "0.5" # 请使用最新版本
tokio = { version = "1.0", features = ["full"] }
基本使用方法
1. 创建中继池
use nostr_relay_pool::{RelayPool, RelayPoolNotification};
use tokio::sync::mpsc;
#[tokio::main]
async fn main() {
// 创建中继URL列表
let relay_urls = vec![
"wss://relay.damus.io".to_string(),
"wss://nostr-pub.wellorder.net".to_string(),
"wss://relay.snort.social".to_string(),
];
// 创建中继池
let (notification_tx, mut notification_rx) = mpsc::channel(100);
let pool = RelayPool::new(notification_tx);
// 添加中继
for url in relay_urls {
pool.add_relay(&url, None).await.unwrap();
}
// 启动中继池
pool.connect().await;
}
2. 订阅事件
use nostr::Filter;
// 创建过滤器 - 订阅特定作者的最新笔记
let filter = Filter::new()
.authors(vec![
"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245".parse().unwrap()
])
.limit(10);
// 订阅
let sub_id = "my-subscription-id".to_string();
pool.subscribe(vec![filter], Some(sub_id.clone()).await;
3. 处理通知
// 在一个单独的task中处理通知
tokio::spawn(async move {
while let Some(notification) = notification_rx.recv().await {
match notification {
RelayPoolNotification::Event(sub_id, event) => {
println!("收到事件 {}: {}", sub_id, event.content);
}
RelayPoolNotification::Message(message) => {
println!("中继消息: {:?}", message);
}
RelayPoolNotification::RelayStatus(url, status) => {
println!("中继 {} 状态变化: {:?}", url, status);
}
_ => {}
}
}
});
4. 发布事件
use nostr::{Event, Keys};
// 创建密钥
let keys = Keys::generate();
// 创建事件
let event = Event::new_text_note("Hello from Rust nostr-relay-pool!", &keys).unwrap();
// 发布到所有中继
pool.publish_event(event).await.unwrap();
高级功能
1. 自定义连接选项
use nostr_relay_pool::RelayOptions;
let options = RelayOptions::new()
.read(true) // 只读
.write(true) // 可写
.retry_secs(5) // 重试间隔5秒
.timeout_secs(10); // 超时10秒
pool.add_relay("wss://custom.relay", Some(options)).await.unwrap();
2. 批量操作
// 批量添加中继
pool.add_relays(vec![
("wss://relay1.com".to_string(), None),
("wss://relay2.com".to_string(), None),
]).await.unwrap();
// 批量取消订阅
pool.unsubscribe(vec!["sub-id-1".to_string(), "sub-id-2".to_string()]).await;
3. 连接状态监控
// 获取所有中继状态
let statuses = pool.relay_statuses().await;
for (url, status) in statuses {
println!("{}: {:?}", url, status);
}
// 断开特定中继
pool.disconnect_relay("wss://relay.damus.io").await.unwrap();
最佳实践
- 错误处理:始终处理可能出现的错误,特别是网络操作
- 资源清理:不再需要时取消订阅并断开连接
- 连接管理:监控中继状态并处理重连逻辑
- 性能考虑:合理设置过滤器以避免过多不必要的事件
完整示例
use nostr_relay_pool::{RelayPool, RelayPoolNotification};
use nostr::{Filter, Keys, Event};
use tokio::sync::mpsc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 初始化
let (notification_tx, mut notification_rx) = mpsc::channel(100);
let pool = RelayPool::new(notification_tx);
// 添加中继
pool.add_relays(vec![
("wss://relay.damus.io".to_string(), None),
("wss://nostr-pub.wellorder.net".to_string(), None),
]).await?;
// 连接
pool.connect().await;
// 订阅
let filter = Filter::new().limit(10);
let sub_id = "example-sub".to_string();
pool.subscribe(vec![filter], Some(sub_id.clone())).await;
// 处理通知
tokio::spawn(async move {
while let Some(notification) = notification_rx.recv().await {
match notification {
RelayPoolNotification::Event(sub_id, event) => {
println!("[{}] 新事件: {}", sub_id, event.content);
}
RelayPoolNotification::RelayStatus(url, status) => {
println!("中继状态更新: {} -> {:?}", url, status);
}
_ => {}
}
}
});
// 发布事件
let keys = Keys::generate();
let event = Event::new_text_note("测试消息", &keys)?;
pool.publish_event(event).await?;
// 保持运行
tokio::signal::ctrl_c().await?;
Ok(())
}