在區域網路内,你要通過一台主機和其他主機進行通信,你需要知道對方的 ip 位址,但是有些時候,你并不知道對方的 ip 位址,因為一般使用 DHCP 動态配置設定 ip 位址的區域網路内,各個主機的 IP 位址是由 DHCP 伺服器來幫你配置設定 IP 位址的。是以在很多情況下,你要知道對方的 IP 位址是比較麻煩的。
mDNS即多點傳播DNS(multicast DNS)。使用5353端口,在内網沒有DNS伺服器時,就會出現此多點傳播資訊。
mDNS 的工作原理
首先,在 IP 協定裡規定了一些保留位址,其中有一個是 224.0.0.251,對應的 IPv6 位址是 [FF02::FB]。
- mDNS 協定規定了一個端口,5353。
- mDNS 基于 UDP 協定。
每個進入區域網路的主機,如果開啟了mDNS服務的話,都會向區域網路内的所有主機多點傳播一個消息,我是誰,和我的IP位址是多少。然後其他也有該服務的主機就會響應,也會告訴你,它是誰,它的IP位址是多少。當然,具體實作要比這個複雜點。
比如,A主機進入區域網路,開啟了 mDNS 服務,并向 mDNS 服務注冊以下資訊:我提供 FTP 服務,我的IP是 192.168.1.101,端口是 21。當B主機進入區域網路,并向 B 主機的 mDNS 服務請求,我要找區域網路内 FTP 伺服器,B主機的 mDNS 就會去區域網路内向其他的 mDNS 詢問,并且最終告訴你,有一個IP位址為 192.168.1.101,端口号是 21 的主機,也就是 A 主機提供 FTP 服務,是以 B 主機就知道了 A 主機的 IP 位址和端口号了。
大概的原理就是這樣子,mDNS提供的服務要遠遠多于這個,當然服務多但并不複雜。
在Apple 的裝置上(電腦,筆記本,iphone,ipad等裝置)都提供了這個服務。很多Linux裝置也提供這個服務。Windows的裝置可能沒有提供,但是如果安裝了iTunes之類的軟體的話,也提供了這個服務。
這樣就可以利用這個服務開發一些區域網路内的自動發現,然後提供一些區域網路内互動的應用了。
ESP8266 中的實作
以下的示例是用一個ESP8266在目前内網中注冊一個mDNS服務,另外查詢網内有哪些可以使用的mDNS,并将其全部列印出來。
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
const char* ssid = "...";
const char* password = "...";
char hostString[16] = {0};
void setup() {
Serial.begin(115200);
delay(100);
Serial.println("\r\nsetup()");
sprintf(hostString, "ESP_%06X", ESP.getChipId());
Serial.print("Hostname: ");
Serial.println(hostString);
WiFi.hostname(hostString);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
if (!MDNS.begin(hostString)) {
Serial.println("Error setting up MDNS responder!");
}
Serial.println("mDNS responder started");
MDNS.addService("esp", "tcp", 8080); // Announce esp tcp service on port 8080
Serial.println("Sending mDNS query");
int n = MDNS.queryService("esp", "tcp"); // Send out query for esp tcp services
Serial.println("mDNS query done");
if (n == 0) {
Serial.println("no services found");
}
else {
Serial.print(n);
Serial.println(" service(s) found");
for (int i = 0; i < n; ++i) {
// Print details for each service found
Serial.print(i + 1);
Serial.print(": ");
Serial.print(MDNS.hostname(i));
Serial.print(" (");
Serial.print(MDNS.IP(i));
Serial.print(":");
Serial.print(MDNS.port(i));
Serial.println(")");
}
}
Serial.println();
Serial.println("loop() next");
}
void loop() {
// put your main code here, to run repeatedly:
}
本文還在持續更新中,後續内容還敬請關注