| Crates.io | hightower-mdns |
| lib.rs | hightower-mdns |
| version | 0.1.3 |
| created_at | 2025-09-30 22:22:13.076855+00 |
| updated_at | 2025-10-03 15:02:39.963866+00 |
| description | A naive Rust implementation of mDNS (Multicast DNS) for advertising and discovering hostnames on a local network |
| homepage | |
| repository | https://github.com/chrishayen/hightower-mdns |
| max_upload_size | |
| id | 1861803 |
| size | 198,602 |
A naive Rust implementation of mDNS (Multicast DNS) for advertising and discovering hostnames on a local network. Implements basic functionality from RFC 6762.
.local per RFC 6762)Add this to your Cargo.toml:
[dependencies]
hightower-mdns = "0.1.3"
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
use hightower_mdns::Mdns;
use std::net::Ipv4Addr;
#[tokio::main]
async fn main() -> std::io::Result<()> {
// Create an mDNS instance with your hostname and local IP
let mdns = Mdns::new("myhost", Ipv4Addr::new(192, 168, 1, 100))?;
// Run the mDNS service (broadcasts and listens for queries)
// Returns a handle for querying and receiving notifications
let mut handle = mdns.run();
// Handle incoming discoveries and responses
loop {
tokio::select! {
Some(response) = handle.discoveries.recv() => {
println!("Discovered: {} at {}", response.hostname, response.ip);
}
Some(response) = handle.responses.recv() => {
println!("Query response: {} at {}", response.hostname, response.ip);
}
}
}
}

use hightower_mdns::Mdns;
use std::net::Ipv4Addr;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mdns = Mdns::new("myhost", Ipv4Addr::new(192, 168, 1, 100))?;
let mut handle = mdns.run();
// Query for a specific host
handle.query("otherhost").await;
// Wait for response
if let Some(response) = handle.responses.recv().await {
println!("Found: {} at {}", response.hostname, response.ip);
}
Ok(())
}
use hightower_mdns::Mdns;
use std::net::Ipv4Addr;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mdns = Mdns::new("myhost", Ipv4Addr::new(192, 168, 1, 100))?;
let mut handle = mdns.run();
loop {
tokio::select! {
Some(response) = handle.discoveries.recv() => {
println!("Discovered: {} at {}", response.hostname, response.ip);
// Query the discovered host
let host = response.hostname.split('.').next().unwrap_or(&response.hostname);
handle.query(host).await;
}
Some(response) = handle.responses.recv() => {
println!("Query response from: {} at {}", response.hostname, response.ip);
}
}
}
}
use hightower_mdns::Mdns;
use std::net::Ipv4Addr;
#[tokio::main]
async fn main() -> std::io::Result<()> {
// Use a custom domain instead of .local
let mdns = Mdns::new("myhost", Ipv4Addr::new(192, 168, 1, 100))?
.with_domain("custom");
let _handle = mdns.run();
// Service is now running in the background
tokio::time::sleep(tokio::time::Duration::from_secs(60)).await;
Ok(())
}
use hightower_mdns::Mdns;
use std::net::Ipv4Addr;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mdns = Mdns::new("myhost", Ipv4Addr::new(192, 168, 1, 100))?;
// Manually send goodbye packet before leaving
mdns.goodbye().await;
Ok(())
}
Multicast DNS (mDNS) enables DNS-like hostname resolution on a local network without requiring a conventional DNS server. It's designed for zero-configuration networking, where devices can discover each other automatically.
Multicast Group: mDNS uses IP multicast address 224.0.0.251 on UDP port 5353. All mDNS-enabled devices on the local network join this multicast group to send and receive DNS queries and responses.
Domain: By default, mDNS uses the .local top-level domain. Hostnames like myhost.local are resolved via mDNS rather than traditional DNS servers.
DNS Record Types: mDNS primarily uses standard DNS record types:
Announcements (Unsolicited Responses): When a device joins the network or periodically thereafter, it multicasts DNS response packets announcing its hostname and IP address. This allows other devices to learn about it without explicitly querying. Announcements are sent with the cache-flush bit set to indicate that receivers should update their cache.
Queries: When a device wants to find a specific hostname, it sends a DNS query to the multicast group. All devices receive the query and check if it matches their hostname.
Responses: If a device's hostname matches a received query, it responds with a DNS answer packet containing its IP address. Responses can be sent either via multicast (so all devices can update their caches) or via unicast (directly to the querier).
Cache Coherency: mDNS records have TTL (Time To Live) values. Devices cache responses and use the TTL to determine when cached data expires. The cache-flush bit in responses signals that old cached data should be replaced.
Goodbye Packets: When a device is about to leave the network gracefully, it sends a multicast announcement with TTL=0, signaling to other devices that they should remove its entry from their cache.
discoveries channelresponses channel[Add your license here]