天天看點

關于mDNS

在區域網路内,你要通過一台主機和其他主機進行通信,你需要知道對方的 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:

}
           
本文還在持續更新中,後續内容還敬請關注
上一篇: 關于SSDP

繼續閱讀