Multicast Application Protocol mDNS for Local Discovery

In computer networks, the Multicast DNS (mDNS) protocol resolves host names to IP addresses in small networks that do not include local name servers. This is a zero-configuration server. mDNS has basically the same programming interface, packet format, and operation mode as the traditional domain name system (DNS).

mDNS was first proposed by Bill Woodcock and Bill Manning in the IETF in 2000. It was finally published as a standard protocol in RFC 6762 by Stuart Cheshire and Marc Krochmal in 2013, and implemented by Apple Bonjour and the open source Avahi software packages. It is included in most Linux distributions (excerpted from Wikipedia).

1. Introduction to mDNS protocol

mDNS is a domain name resolution protocol for local networks, which uses port 5353 and multicast address 224.0.0.251. It is an application protocol running on UDP. Unlike traditional DNS protocols, mDNS does not require a DNS server to perform domain name resolution, which saves the trouble of configuring domain name servers on local networks.

After a host with mDNS service enabled joins a LAN, it will first multicast a message to the multicast address 224.0.0.251 of the LAN, "Who am I? What is my IP address? What are the services and port numbers I provide?". After receiving the message, other hosts with mDNS service enabled on the LAN will record the message and respond with "Who is it? What is its IP address? What is the service and port number it provides?". If a host wants to query the mDNS domain name, it will first query its own cache information. If it is not found, it will multicast a query to the LAN to ask for the IP address, services, and port numbers of the domain name.

Then how can a host distinguish whether a domain name is from DNS or mDNS when querying a domain name?

mDNS domain names differ from DNS domain names by the suffix ".local".

2. Using mDNS component based on ESP-IDF

📌 Note: mDNS component

ESP-IDF provides the mDNS component, which helps you develop applications. You may refer to the mDNS service in the ESP-IDF Programming Guide for relevant interfaces.

For mDNS component, please visit https://github.com/espressif/esp-idf/tree/v4.3.2/components/mdns. For mDNS service, please visit https://bookc3.espressif.com/mdns.

This section mainly introduces how to use the mDNS component for developing devices to be discovered.

esp_err_t esp_mdns_discovery_start(void)
{
    char *host_name = "my_smart_light";
    char *instance_name = "esp32c3_smart_light";

    //Initialise the mDNS component
    if (mdns_init() ! = ESP_OK) {
        ESP_LOGE(TAG, "mdns_init fail");
        return ESP_FAIL;
    }

    //Set host name (the DNS domain name tag to be queried by other hosts)
    if (mdns_hostname_set(host_name) ! = ESP_OK) {
        ESP_LOGE(TAG, "mdns_hostname_set fail");
        goto err;
    }
    ESP_LOGI(TAG, "mdns hostname set to: [%s]", host_name);

    //Set mDNS instance name to be discovered by mDNS LAN
    if (mdns_instance_name_set(instance_name) ! = ESP_OK) {
        ESP_LOGE(TAG, "mdns_instance_name_set fail");
        goto err;
    }
 
    //Set service TXT field data (optional)
    mdns_txt_item_t serviceTxtData[1] = {
        {"board", "esp32c3"}
    };

    //Add HTTP service; port 80 corresponds to mDNS service.
    //The second parameter (application layer protocol) and the third parameter (transport layer protocol) need to correspond to each other.
    if (mdns_service_add(instance_name, "_http", "_tcp", 80, serviceTxtData, 1) ! = ESP_OK) {
        ESP_LOGE(TAG, "mdns_instance_name_set fail");
        goto err;
    }

    //Set service TXT field data
    if (mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") ! =ESP_OK){
        ESP_LOGE(TAG, "mdns_service_txt_item_set fail");
        goto err;
    }
        return ESP_OK;
err:
    mdns_free();
    return ESP_FAIL;
}

The above code implements the mDNS service with the domain name my_smart_light and the node esp32c3_smart_light. Your other hosts can query the node esp32c3_smart_light through the mDNS service. The smart light host will reply with its own domain name (my_smart_light), corresponding IP address, provided service (HTTP), corresponding server port (80), and TXT node field (path=/foobar board=esp32c3).

📝 Source code

For complete code of the example, please refer to book-esp32c3-iot-projects/test_case/mdns_discovery.

You can use the Windows command dns-sd -L esp32c3_smart_light_http to query the information of the host in the LAN. The command is as follows:

c:\Users> dns-sd -L esp32c3_smart_light_http
Lookup esp32c3_smart_light._http._tcp.local
14:25:09.682 esp32c3_smart_light._http._tcp.local. can be reached at my_smart_light.local.:80 (interface 6)
 path=/foobar board=esp32c3

📌 NOTE: "Bonjour"

"Bonjour" is a network configuration software that supports zero-configuration networking service and can automatically discover computers, devices, and services on the IP network. It needs to be installed before using the command dns-sd. You can download Bonjour at https://bonjour.en.softonic.com/.

You can also use the Linux command avahi-browse -a --resolve to query service information of all mDNS hosts in the LAN. The command is as follows:

# avahi-browse -a --resolve
= enp1s0 IPv4 esp32c3_smart_light Web Site local
    hostname = [my_smart_light.local]
    address = [192.168.3.5]
    port = [80]
    txt = ["board=esp32c3" "path=/foobar"]