01 · Problem
Wofür braucht man das?
Geräte im selben LAN sollen Dienste finden, ohne einen zentralen DNS-Server oder fest konfigurierte IP-Adressen zu benötigen.
02 · Denkmodell
Das mentale Modell
mDNS ist eine gemeinschaftliche Multicast-Zone. Queries werden nicht wie RPCs korreliert, sondern Antworten für Name und Typ innerhalb eines kurzen Fensters gesammelt.
Bietet ein deterministisches lokales Discovery-Modell und einen explizit gestarteten Multicast-Adapter. MDNS prüft TTL und Cleanup lokal; NetworkMDNS sammelt verzögerte Netzwerkantworten über multicast-dns. CI injiziert den Transport; Interface-Auswahl und geräteübergreifende Zuverlässigkeit bleiben Integrationsarbeit.
03 · Kontrollfluss
Was passiert in welcher Reihenfolge?
- UDP-Multicast-Socket für Port 5353 öffnen und Response-Listener zuerst registrieren.
- Standardkonforme Frage mit Name und Typ senden.
- Passende Answer- und Additional-Records während eines Sammelfensters erfassen.
- Records normalisieren und deduplizieren, danach Listener und Timer entfernen.
- Beim Shutdown alle ausstehenden Queries abbrechen und Socket schließen.
04 · Bauteile
Die entscheidenden Verträge
MDNS.query / announce / destroyFindet passende lokale Records, veröffentlicht sie und entfernt eigene Records.DNSRecord / DNSTypeBeschreibt unterstützte Recorddaten und Abfragetypen.05 · Selbst bauen
Selbst implementieren
Verwende das normale DNS-Protokoll und korreliere über Name, Typ und Zeitfenster statt über proprietäre Request-IDs.
- Modelliere Record-Typ und Payload als diskriminierte Union.
- Registriere Listener vor dem Senden und sammle mehrere Antworten bis zum Timeout.
- Bereinige Listener, Timeout und Pending-Promise bei Erfolg, Fehler, Abort und Shutdown.
async function query(name: string, type: string, signal: AbortSignal) {
const answers: unknown[] = [];
const onResponse = (packet: any) => {
for (const record of [...packet.answers, ...packet.additionals]) {
if (record.name === name && (type === "ANY" || record.type === type)) {
answers.push(record);
}
}
};
socket.on("response", onResponse);
try { socket.query({ questions: [{ name, type }] }); await delay(500, signal); }
finally { socket.off("response", onResponse); }
return deduplicate(answers);
}06 · Verifizieren
Was solltest du testen?
- Mehrere Antworten, Duplikate und fremde Name/Typ-Kombinationen werden korrekt behandelt.
- Timeout, Abort und destroy entfernen Listener und settle'n jedes Promise genau einmal.
- PTR, SRV, TXT, A und AAAA behalten jeweils die richtige Datenform.
Selbst ausprobieren
Formuliere die erste Prüfaussage als fehlschlagenden Test, implementiere die kleinste Korrektur und ergänze einen Grenzfall.
Mehrere Antworten, Duplikate und fremde Name/Typ-Kombinationen werden korrekt behandelt.
Ansatz vergleichen
Dein Test sollte beim gezielten Verletzen der Invariante fehlschlagen und nach der Korrektur wieder bestehen. Halte den Aufbau deterministisch und prüfe ein beobachtbares Ergebnis.
07 · Grenzen
Kompromisse und Stolperfallen
- mDNS funktioniert nur innerhalb einer Multicast-Domain und ist kein Internet-Service-Discovery.
- Antworten sind untrusted; Service-Metadaten beweisen keine Identität.
- Betriebssysteme und Netzwerke können Multicast filtern oder bündeln.
MDNS prüft TTL und Cleanup lokal; NetworkMDNS sammelt verzögerte Netzwerkantworten über multicast-dns. CI injiziert den Transport; Interface-Auswahl und geräteübergreifende Zuverlässigkeit bleiben Integrationsarbeit.
08 · Weiterdenken
Quellcode und verwandte Ideen
yarn tsx packages/mdns/examples/basic.ts