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)
}

注意事项

  1. SSDP使用UDP多播地址239.255.255.250和端口1900
  2. 确保网络允许SSDP通信(防火墙设置)
  3. 搜索响应可能会有延迟,适当设置超时时间
  4. 设备可能会发送多个响应

完整示例:发现所有媒体服务器

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功能实现,可以方便地集成到各种网络应用和设备发现场景中。

回到顶部