Так. С запросом мы покончили. Теперь поговорим об ответе или 'Response', а для этого надо разобраться что такое 'RR' записи. Означенные записи формируются NS сервером и располагаются только в ответе и строго следом за полем запроса. То есть 'Answer' и все последующие состоят из некоторого количества 'RR' записей различного формата. В них передаются в качестве информации и IP адреса и названия серверов и просто текстовая информация. Подбробно все типы этих записей приведены в RFC 1035, они довольно похожи друг на друга и различаются лишь мелкими деталями. Так что я буду говорить только об интересующих меня. Аббревиатура 'RR' означает 'Resource Record', это официальное название из документа.
В общем случае RR запись выглядит так :
NAME ................ up to 255 bytes + 1 ('\0') TYPE ................ 2 bytes (UINT) CLASS ............... 2 bytes (UINT) TTL ................. 4 bytes (signed 32 bits number - 'long') RDLENGTH ............ 2 bytes (UINT) RDATA ............... variable, depend on query NAME : название хоста, к которому относится запись TYPE : тип представляемой информации (о типах см. выше.) CLASS : класс сети (?) в нашем случае всегда 'IN' (01) TTL : время хранения информации в секундах - 86400 - 1 сутки RDLENGTH : длина блока информации в байтах RDATA : блок представляемой информации.
Так вот, немного повторяясь скажу как сервер формирует ответ: он берет мой запрос, роется в своих записях, находит интересующую меня информацию, выписывает ее по разделам, прикрепляет к моему же запросу и высылает мне. Поэтому часть ответа на мой запрос (Header + Question) почти полная копия моего запроса, чтобы напомнить мне, что же я спрашивал. Вторая часть - собственно ответ. Если я запрашиваю IP адрес какого-то нужного мне хоста, то получу этот адрес, если таковой (хост) имеется в наличии, и серверу известно об этом. И кое-что еще.
Ну, как ? Впечатляет ? Это еще не все. Теперь на очереди рассмотрение как предствляются имена.
Кроме того, что имя хоста составляется из меточек с длиной, оно еще может быть и упаковано, довольно простым способом, но тем не менее.
Без упаковки : имя хоста www.netvision.net.il будет выглядеть как:
03 www 09 netvision 03 net 02 il 00
Упаковывают имя используя указатель, он представляет собой два байта, причем первый используется в качестве семафора, два старших бита этого семафора установлены в 1, а остальные не определены, обычно в них нули - 11хх хххх. Второй байт является смещением от начала запроса, т.е от первого байта идентификатора. Так вот, если серверу надо в ответе написать имя хоста dns.netvision.net.il, он пишет:
03 dns C0 10
и как бы пристегивает недостающую часть из другого имени, где и есть означенный указатель. Получается существенный выигрыш в объеме.
Никакой путаницы, Б-же упаси ! Меточки ограничены по длине 63+1, стало быть два старших бита всегда свободны. Так что если ваша программа просматривает метки, она не ошибется, если ей попадется указатель.
Насколько это делается в запросе, я пока не могу сказать, надо посмотреть чужие исходники более внимательно. Линуховский NSlookup, к примеру. Но не вижу причины не использовать этот способ и в запросе.