Что такое DNS?

«Что такое DNS?» — вопрос из категории Сети, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

DNS (Domain Name System) — это распределённая иерархическая система, преобразующая удобные для человека доменные имена (например, www.example.com) в машиночитаемые IP-адреса (например, 93.184.216.34). Это фундаментальный протокол прикладного уровня интернета.

Как это работает в контексте C++ сетевого программирования: Перед установкой соединения по TCP или отправкой UDP-пакета на хост по имени, программа должна разрешить это имя в адрес. Для этого используются функции, такие как getaddrinfo, которые инкапсулируют сложность DNS-запроса.

Пример разрешения имени в C++ с использованием сокетов Беркли:

#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

std::string resolve_hostname(const std::string& hostname) {
    struct addrinfo hints = {}, *res;
    hints.ai_family = AF_UNSPEC;    // Принимаем IPv4 или IPv6
    hints.ai_socktype = SOCK_STREAM; // Для TCP

    int status = getaddrinfo(hostname.c_str(), nullptr, &hints, &res);
    if (status != 0) {
        throw std::runtime_error(gai_strerror(status));
    }

    // Берём первый адрес из списка и преобразуем в строку
    char ipStr[INET6_ADDRSTRLEN];
    void* addr;
    if (res->ai_family == AF_INET) { // IPv4
        addr = &((struct sockaddr_in*)res->ai_addr)->sin_addr;
    } else { // IPv6
        addr = &((struct sockaddr_in6*)res->ai_addr)->sin6_addr;
    }
    inet_ntop(res->ai_family, addr, ipStr, sizeof(ipStr));

    freeaddrinfo(res);
    return std::string(ipStr);
}

int main() {
    try {
        std::string ip = resolve_hostname("google.com");
        std::cout << "Resolved IP: " << ip << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    return 0;
}

Важные для разработчика детали:

  • Кеширование: DNS-ответы кешируются на разных уровнях (ОС, провайдер, локальный резолвер), что ускоряет повторные запросы.
  • Типы записей: Помимо основной записи A (IPv4) или AAAA (IPv6), существуют MX (для почты), CNAME (алиас), PTR (обратное разрешение).
  • Протокол: Обычно работает поверх UDP (порт 53) для запросов, но может использовать TCP для больших ответов или зонных трансферов.
  • Асинхронное разрешение: В высокопроизводительных приложениях (например, асинхронных серверах) используют неблокирующие или асинхронные DNS-клиенты, чтобы не блокировать поток на время сетевого запроса.