#服务发现 #mdns #dns #dns-queries #dns-sd #ip-address #zeroconf

simple-mdns

用于服务发现的mDNS(DNS-SD)的Rust实现

23个版本

0.6.2 2024年3月25日
0.5.0 2023年10月17日
0.4.1 2023年7月9日
0.4.0 2022年12月10日
0.2.1 2021年7月10日

#1139 in 网络编程

Download history 98/week @ 2024-04-28 98/week @ 2024-05-05 123/week @ 2024-05-12 264/week @ 2024-05-19 398/week @ 2024-05-26 589/week @ 2024-06-02 561/week @ 2024-06-09 686/week @ 2024-06-16 623/week @ 2024-06-23 618/week @ 2024-06-30 540/week @ 2024-07-07 294/week @ 2024-07-14 708/week @ 2024-07-21 366/week @ 2024-07-28 519/week @ 2024-08-04 606/week @ 2024-08-11

每月2,211次下载
用于 2 crate

MIT 许可协议

265KB
6K SLoC

简单mDNS

纯Rust实现的mDNS和DNS-SD协议

此crate提供两种服务发现版本,同步版本位于模块 sync_discovery 中,异步版本位于 async_discovery 中。

特性

使用服务发现必须启用至少一个特性

  • sync: 提供了 sync_discovery 模块
  • async-tokio: 使用tokio运行时提供 async_discovery 模块

ServiceDiscovery

广播已注册的地址并查询同一网络上的可用实例。
需要提供实例和服务名称

    # #[cfg(feature = "sync")] {
    use simple_mdns::sync_discovery::ServiceDiscovery;
    use simple_mdns::InstanceInformation;
    use std::str::FromStr;

    let mut discovery = ServiceDiscovery::new(
        InstanceInformation::new("a".into()).with_socket_address("192.168.1.22:8090".parse().expect("Invalid socket address")),
        "_mysrv._tcp.local", 
        60
    ).expect("Failed to start service discovery");

    // Removing service from discovery
    discovery.remove_service_from_discovery();
    # }

OneShotMdnsResolver (传统mDNS)

单次解析器被认为是传统的,并不完全符合mDNS协议,但如果只有一个服务实例(或需要)的话,它们对于服务发现很有用

工作原理

单次解析器或查询发送一个多播DNS查询以在网络中查找可用的服务。

  • 只需要IP地址(端口固定或已知),发送一个A或AAAA查询。
  • 需要IP地址和端口,发送一个SRV查询。

由于mDNS是一个广为人知的协议,你可以在网络中的任何mDNS响应器中注册你的服务,并且它们应该能够回复有关你的服务的请求信息。

查询示例

    # #[cfg(feature = "sync")] {
    use simple_mdns::sync_discovery::OneShotMdnsResolver;
    let resolver = OneShotMdnsResolver::new().expect("Failed to create resolver");
    // querying for IP Address
    let answer = resolver.query_service_address("_myservice._tcp.local").expect("Failed to query service address");
    println!("{:?}", answer);
    // IpV4Addr or IpV6Addr, depending on what was returned
    
    let answer = resolver.query_service_address_and_port("_myservice._tcp.local").expect("Failed to query service address and port");
    println!("{:?}", answer);
    // SocketAddr, "127.0.0.1:8080", with a ipv4 or ipv6
    # }

SimpleMdnsResponder

如果你网络中没有mDNS响应器,或者由于某些原因不想使用现有的响应器。

此响应器将通过多播监听网络中的任何mDNS查询,并仅对添加的资源进行回复。

此结构依赖于 simple-dns crate,并且必须将其作为依赖项添加

    # #[cfg(feature = "sync")] {
    use simple_mdns::sync_discovery::SimpleMdnsResponder;
    use simple_dns::{Name, CLASS, ResourceRecord, rdata::{RData, A, SRV}};
    use std::net::Ipv4Addr;


    let mut responder = SimpleMdnsResponder::new(10);
    let srv_name = Name::new_unchecked("_srvname._tcp.local");

    responder.add_resource(ResourceRecord::new(
        srv_name.clone(),
        CLASS::IN,
        10,
        RData::A(A { address: Ipv4Addr::LOCALHOST.into() }),
    ));

    responder.add_resource(ResourceRecord::new(
        srv_name.clone(),
        CLASS::IN,
        10,
        RData::SRV(SRV {
            port: 8080,
            priority: 0,
            weight: 0,
            target: srv_name
        })
    ));
    # }

IPV6

现在支持使用 NetworkScope 枚举。

    # // This is test is marked as no_run because IPV6 is not available in github actions.
    # #[cfg(feature = "sync")] {
    use simple_mdns::sync_discovery::ServiceDiscovery;
    use simple_mdns::{NetworkScope, InstanceInformation};
    use std::str::FromStr;

    let mut discovery = ServiceDiscovery::new_with_scope(
        InstanceInformation::new("a".into()), 
        "_mysrv._tcp.local", 
        60, 
        None, 
        NetworkScope::V6,
    ).expect(" Service Name");
    # }

注意:在MacOS上未进行测试。

依赖项

~0.7–9.5MB
~73K SLoC