4 个版本
0.3.2 | 2023 年 9 月 26 日 |
---|---|
0.3.1 | 2023 年 4 月 22 日 |
0.3.0 | 2023 年 1 月 8 日 |
0.2.0 | 2022 年 12 月 30 日 |
0.1.0 |
|
#1407 在 网络编程 中排名
每月 28 次下载
76KB
1.5K SLoC
📡 Searchlight
Searchlight 是一个简单、轻量级且易于使用的 mDNS 服务器和客户端库,即使您只有基本的 mDNS 知识也可以轻松使用。
简单来说,Searchlight 是一个用于在本地网络上广播和发现“服务”的库。这项技术与 Chromecast、AirDrop、Philips Hue 等产品使用的相同技术。
Searchlight 注重用户界面设计。 该库的显著特点是它跟踪网络中服务的存在,并在它们出现和消失时通知您,这样您可以相应地更新您的用户界面,提供响应速度快、直观且熟悉的用户体验,类似于 WiFi、蓝牙、Chromecast 等扫描列表。
- 🌐 IPv4 和 IPv6 - 支持 IPv4 和 IPv6。
- ✨ 操作系统支持 - 支持 Windows、macOS 以及大多数 UNIX 系统。
- 📡 广播 - 向网络发送服务公告并响应发现请求。(mDNS 服务器)
- 👽 发现 - 发现网络上的服务并跟踪它们的存在。(mDNS 客户端)
- 🧵 单线程 - 由于使用了 Tokio 异步运行时和任务调度器,Searchlight 只在单个线程上运行。
- 🤸 灵活的 API - 无异步、无流、无通道、无废话。只需提供一个事件处理函数,然后根据您的喜好在应用程序和 Searchlight 之间建立桥梁。
- 👻 背景运行时 - 发现和广播都可以在单独的线程上后台运行,提供必要的优雅关闭句柄。
- 📨 UDP - 所有网络,包括发现和广播,都是无连接的,并通过 UDP 完成。
- 🔁 Loopback - 支持接收由同一套接字发送的数据包,旨在用于测试。
- 🎯 接口定向 - 支持针对特定网络接口进行发现和广播。
用法
将Searchlight添加到您的Cargo.toml
文件中
[dependencies]
searchlight = "0.3.1"
要了解更多关于如何使用Searchlight的信息,请参阅文档。
示例
👽 发现
在网络中找到所有的Chromecast设备。
use searchlight::{
discovery::{DiscoveryBuilder, DiscoveryEvent},
dns::{op::DnsResponse, rr::RData},
net::IpVersion,
};
fn get_chromecast_name(dns_packet: &DnsResponse) -> String {
dns_packet
.additionals()
.iter()
.find_map(|record| {
if let Some(RData::SRV(_)) = record.data() {
let name = record.name().to_utf8();
let name = name.strip_suffix('.').unwrap_or(&name);
let name = name.strip_suffix("_googlecast._tcp.local").unwrap_or(&name);
let name = name.strip_suffix('.').unwrap_or(&name);
Some(name.to_string())
} else {
None
}
})
.unwrap_or_else(|| "Unknown".into())
}
DiscoveryBuilder::new()
.service("_googlecast._tcp.local.")
.unwrap()
.build(IpVersion::Both)
.unwrap()
.run(|event| match event {
DiscoveryEvent::ResponderFound(responder) => {
println!(
"Found Chromecast {} at {}",
get_chromecast_name(&responder.last_response),
responder.addr.ip()
);
}
DiscoveryEvent::ResponderLost(responder) => {
println!(
"Chromecast {} at {} has gone away",
get_chromecast_name(&responder.last_response),
responder.addr.ip()
);
}
DiscoveryEvent::ResponseUpdate { .. } => {}
})
.unwrap();
📡 广播
在网络中广播一项服务,并验证其是否可被发现。
use searchlight::{
broadcast::{BroadcasterBuilder, ServiceBuilder},
discovery::{DiscoveryBuilder, DiscoveryEvent},
net::IpVersion,
};
use std::{
net::{IpAddr, Ipv4Addr},
str::FromStr,
};
let (found_tx, found_rx) = std::sync::mpsc::sync_channel(0);
let broadcaster = BroadcasterBuilder::new()
.loopback()
.add_service(
ServiceBuilder::new("_searchlight._udp.local.", "HELLO-WORLD", 1234)
.unwrap()
.add_ip_address(IpAddr::V4(Ipv4Addr::from_str("192.168.1.69").unwrap()))
.add_txt_truncated("key=value")
.add_txt_truncated("key2=value2")
.build()
.unwrap(),
)
.build(IpVersion::V4)
.unwrap()
.run_in_background();
let discovery = DiscoveryBuilder::new()
.loopback()
.service("_searchlight._udp.local.")
.unwrap()
.build(IpVersion::V4)
.unwrap()
.run_in_background(move |event| {
if let DiscoveryEvent::ResponderFound(responder) = event {
found_tx.try_send(responder).ok();
}
});
println!("Waiting for discovery to find responder...");
println!("{:#?}", found_rx.recv().unwrap());
println!("Shutting down...");
broadcaster.shutdown().unwrap();
discovery.shutdown().unwrap();
println!("Done!");
贡献
除非您明确声明,否则您有意提交以包含在您的工作中的任何贡献,根据MIT许可证定义,将双重许可如上,不附加任何额外条款或条件。
依赖项
~8–21MB
~259K SLoC