Rust SSDP客户端库ssdp-client的使用:实现简单服务发现协议(SSDP)的设备搜索与网络服务发现
Rust SSDP客户端库ssdp-client的使用:实现简单服务发现协议(SSDP)的设备搜索与网络服务发现
ssdp-client是一个用于在网络上发现设备和服务、通知和订阅的异步库。
SSDP代表简单服务发现协议(Simple Service Discovery Protocol),它是一种在本地网络上分发消息的协议,用于设备和服务相互发现。SSDP最常见于实现UPnP的设备中,因为它被用作该标准的发现机制。
示例用法
以下是内容中提供的示例代码:
use futures::prelude::*;
use std::time::Duration;
use ssdp_client::SearchTarget;
let search_target = SearchTarget::RootDevice;
let mut responses = ssdp_client::search(&search_target, Duration::from_secs(3), 2, None).await?;
while let Some(response) = responses.next().await {
println!("{:?}", response?);
}
完整示例代码
以下是一个更完整的SSDP客户端实现示例:
use futures::prelude::*;
use std::time::Duration;
use ssdp_client::SearchTarget;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 设置搜索目标为根设备
let search_target = SearchTarget::RootDevice;
// 发起SSDP搜索请求
// 参数说明:
// - 搜索目标
// - 超时时间(3秒)
// - 最大跳数(2)
// - 可选的多播地址(这里使用None表示默认)
let mut responses = ssdp_client::search(&search_target, Duration::from_secs(3), 2, None).await?;
println!("开始搜索网络中的UPnP设备...");
// 遍历并打印所有响应
while let Some(response) = responses.next().await {
match response {
Ok(device) => {
println!("发现设备:");
println!(" 位置: {}", device.location());
println!(" 服务器: {}", device.server());
println!(" 唯一服务名称: {}", device.usn());
println!(" 缓存控制: {}", device.cache_control());
println!();
}
Err(e) => eprintln!("接收设备响应时出错: {}", e),
}
}
Ok(())
}
安装
在你的项目目录中运行以下Cargo命令:
cargo add ssdp-client
或者在Cargo.toml中添加以下行:
ssdp-client = "2.1.0"
许可证
可选择以下任一许可证:
- Apache License, Version 2.0
- MIT license
贡献
请在提交任何拉取请求前使用rustfmt格式化代码。
除非您明确声明,否则根据Apache-2.0许可证,您有意提交的任何贡献都将按上述方式双重许可,不附加任何其他条款或条件。
1 回复
Rust SSDP客户端库 ssdp-client
使用指南
简介
ssdp-client
是一个用于实现简单服务发现协议(SSDP)的Rust库,它允许你在本地网络中搜索UPnP设备和服务。SSDP是UPnP(通用即插即用)协议的基础,常用于发现网络设备如智能电视、媒体服务器、路由器等。
主要功能
- 发送M-SEARCH请求发现网络设备
- 监听SSDP通知消息
- 解析设备响应和通知
- 支持IPv4和IPv6
安装
在Cargo.toml中添加依赖:
[dependencies]
ssdp-client = "0.1"
基本使用方法
1. 搜索网络设备
use ssdp_client::SearchTarget;
use std::time::Duration;
async fn search_devices() -> Result<(), Box<dyn std::error::Error>> {
// 创建搜索请求
let search_target = SearchTarget::RootDevices;
let timeout = Duration::from_secs(3);
// 发送搜索请求并接收响应
let responses = ssdp_client::search(&search_target, timeout, 2).await?;
// 处理响应
for response in responses {
println!("发现设备:");
println!("位置: {}", response.location());
println!("USN: {}", response.usn());
println!("服务类型: {}", response.search_target());
println!("缓存时间: {}秒", response.cache_control());
println!();
}
Ok(())
}
#[tokio::main]
async fn main() {
if let Err(e) = search_devices().await {
eprintln!("错误: {}", e);
}
}
2. 监听通知消息
use ssdp_client::NotifyHeaders;
use std::time::Duration;
async fn listen_notifications() -> Result<(), Box<dyn std::error::Error>> {
// 创建通知接收器
let mut receiver = ssdp_client::listen_notify().await?;
println!("开始监听SSDP通知...");
// 接收通知消息
while let Ok(notification) = receiver.recv_timeout(Duration::from_secs(10)).await {
match notification {
NotifyHeaders::Alive(alive) => {
println!("设备上线通知:");
println!("USN: {}", alive.usn);
println!("位置: {}", alive.location);
println!("服务类型: {}", alive.notification_type);
println!("缓存时间: {}秒", alive.cache_control);
},
NotifyHeaders::Update(update) => {
println!("设备更新通知:");
println!("USN: {}", update.usn);
println!("位置: {}", update.location);
println!("新USN: {}", update.new_usn);
},
NotifyHeaders::Byebye(byebye) => {
println!("设备下线通知:");
println!("USN: {}", byebye.usn);
println!("服务类型: {}", byebye.notification_type);
}
}
println!();
}
Ok(())
}
#[tokio::main]
async fn main() {
if let Err(e) = listen_notifications().await {
eprintln!("错误: {}", e);
}
}
高级用法
自定义搜索目标
use ssdp_client::SearchTarget;
// 搜索特定类型的设备
let media_server_target = SearchTarget::URN("schemas-upnp-org", "device", "MediaServer", 1);
// 搜索特定服务
let content_directory_target = SearchTarget::URN("schemas-upnp-org", "service", "ContentDirectory", 1);
处理设备描述信息
发现设备后,通常需要获取设备的详细描述:
use reqwest;
async fn fetch_device_description(location: &str) -> Result<String, Box<dyn std::error::Error>> {
let resp = reqwest::get(location).await?;
let description = resp.text().await?;
Ok(description)
}
注意事项
- SSDP使用UDP多播地址239.255.255.250和端口1900
- 确保网络允许SSDP通信(防火墙设置)
- 搜索响应可能会有延迟,适当设置超时时间
- 设备可能会发送多个响应
完整示例:发现所有媒体服务器
use ssdp_client::SearchTarget;
use std::time::Duration;
async fn discover_media_servers() -> Result<(), Box<dyn std::error::Error>> {
let target = SearchTarget::URN("schemas-upnp-org", "device", "MediaServer", 1);
let timeout = Duration::from_secs(5);
println!("搜索媒体服务器...");
let responses = ssdp_client::search(&target, timeout, 3).await?;
if responses.is_empty() {
println!("未发现媒体服务器");
} else {
println!("发现 {} 个媒体服务器:", responses.len());
for (i, response) in responses.iter().enumerate() {
println!("\n服务器 #{}:", i + 1);
println!("名称: {}", response.server());
println!("位置: {}", response.location());
println!("USN: {}", response.usn());
}
}
Ok(())
}
#[tokio::main]
async fn main() {
if let Err(e) = discover_media_servers().await {
eprintln!("错误: {}", e);
}
}
这个库为Rust开发者提供了简单而强大的SSDP功能实现,可以方便地集成到各种网络应用和设备发现场景中。