Я пытаюсь понять протоколы прикладного уровня в стеке TCP / IP. Я знаю, что протоколы HTTP и DNS остаются на верхнем уровне (уровне приложений). Итак, когда браузер хочет получить доступ к ресурсу, он должен отправить запрос на HTTP-сервер, например:
GET www.pippo.it/hello.htm HTTP/1.1
Выполняя этот запрос в соответствии с правилами протокола HTTP, он использует URL-адрес страницы, а не IP-адрес.
Я знаю, что DNS-запрос необходим для преобразования URL в IP. Итак, мой вопрос: вызывает ли HTTP протокол DNS? Мне это кажется невозможным, поскольку оба являются протоколами верхнего уровня (так что DNS не может предоставлять услуги HTTP). Точно так же даже TCP (который остается на более низком уровне) не может запрашивать услугу на протоколе более высокого уровня, таком как DNS.
Так когда же происходит запрос DNS? А кто выполняет такую просьбу?
Рассматриваемый HTTP-запрос на самом деле недействителен, если браузер не обращается к посреднику (прокси).
Ваш пример будет немного больше похож на следующий, если бы браузер напрямую общался с веб-сервером:
GET /hello.htm HTTP/1.1
Host: www.pippo.it
Теперь, чтобы представить это в перспективе, рассмотрим модель OSI:
У нас действуют 3 системы:
Используются следующие протоколы снизу вверх (минимальное значение - OP):
Связь HTTP осуществляется по протоколу TCP (TCP находится поверх протокола IP), тогда как связь DNS в этом случае осуществляется по протоколу UDP (UDP также находится поверх протокола IP).
Вот краткая последовательность общения:
В клиент, запустив браузер, спрашивает DNS сервер для A
запись для www.pippo.it
, используя протокол UDP.
1.1. На клиенте именно операционная система выполняет часть разрешения и обращается к браузеру - браузер никогда не общается с DNS-сервером напрямую, а через ОС, вызывая gethostbyname () или новее getaddrinfo (). В Windows порядок, в котором ОС разрешает адреса, скорее всего, определяется чем-то вроде этот, в то время как в Linux приоритет разрешения определяется /etc/nsswitch.conf
В DNS сервер, используя протокол UDP, отвечает на клиент с записью / IP-адресом, если он существует
В клиент открывает TCP-соединение через порт 80 веб сервер и пишет следующий текст:
HTTP-запрос:
GET /hello.htm HTTP/1.1
Host: www.pippo.it
Вы можете имитировать то же самое, сделав что-то вроде этого в консоли или командной строке:
> telnet www.pippo.it 80
Trying 195.128.235.49...
Connected to www.pippo.it.
Escape character is '^]'.
GET /hello.htm HTTP/1.1
Host: www.pippo.it
за которыми следуют две пустые строки. Если запрошенный контент существует, веб-сервер распечатает его на экране. Если на другой стороне есть браузер, текст ответа анализируется браузером, и все теги, ссылки, сценарии и изображения отображаются на том, что мы называем веб-страницей.
На самом деле есть еще несколько деталей, например браузеры могут кэшировать IP-адреса, если вы уже посетили какой-либо домен, поэтому разрешение DNS становится ненужным. Кроме того, современные браузеры могут попытаться выполнить разрешение до того, как оно вам действительно понадобится (Предварительная выборка DNS), чтобы ускорить просмотр.
Кроме того, ваш компьютер может иметь статические записи в hosts
файл. Если запись соответствует запросу, сначала используется локальная статическая запись, и ни один DNS-сервер никогда не связывается. Это можно настроить, и это не обязательно так, но это значение по умолчанию в операционных системах, с которыми я знаком.
HTTP передается через TCP, который является протоколом IP. Чтобы сделать HTTP-запрос, браузер должен открыть TCP-соединение, и для этого ему нужен IP-адрес назначения (то есть IP-адрес сервера). Чтобы разрешить имя хоста сервера, он должен, таким образом, выдать DNS-запрос (обычно сам DNS-запрос отправляется операционной системой, когда программа вызывает свои функции разрешения имен; однако ничто не мешает программе отправлять DNS-запросы самостоятельно на DNS-сервер) . Как только соединение установлено, оно может отправить свой HTTP-запрос, который содержит путь к запрошенному ресурсу и Хост поле с именем хоста сервера (например, Host: www.pippo.it
). Имя хоста не перейдите в строку запроса (на самом деле это будет GET /hello.htm HTTP/1.1
), за исключением случаев, когда запрос отправляется на прокси-сервер HTTP (и в этом случае присутствует полный URL-адрес, включая часть протокола, например GET http://www.pippo.it/hello.htm HTTP/1.1
),
Процедура выглядит так:
http://www.pippo.it/hello.htm
Браузер разбивает это на три части:
http
www.pippo.it
/hello.htm
(более сложный URL может иметь и другие части, я пока проигнорирую эту возможность)
Браузер знает, что для создания IP-соединения ему нужен IP-адрес. Чтобы получить IP-адрес, ему необходимо использовать DNS (если адрес не кэширован).
8.8.8.8
.Браузер строит следующее многоуровневое соединение:
8.8.8.8
A
запись для имени хоста www.pippo.it
Конечно, я опускаю много деталей, например, о точный формат используемых пакетов.
www.pippo.it
, скажем, это 10.11.12.13
http
во внутренней таблице и узнает, что он должен использовать порт 80.Браузер строит следующее многоуровневое соединение:
10.11.12.13
Уровень HTTP: создайте HTTP-запрос для URL /hello.htm
на хосте www.pippo.it
(потому что компьютер на 10.11.12.13
может размещать несколько доменов, поэтому необходимо знать, какой из них желателен)
GET /hello.htm HTTP/1.1
Host: www.pippo.it
...
Конечно, я опускаю все детали рукопожатия TCP и тому подобное.
hello.htm
И для хорошей меры я упомяну, что теперь браузер проверяет содержимое этого ответа и определяет все необходимые дополнительные ресурсы: изображения, CSS, Javascript и т. Д. Затем он повторяет весь этот процесс для каждого такого ресурса.