WinSock: Получение хоста по адресуВ недавнем примере мы делали http-запрос с помощью синхронного сокета. Мы обращались к конкретному серверу, зная его ip. Непорядок, сегодня займёмся определением ip-адреса по доменному имени, по адресу сайта.

MSDN по крайней мере предлагает нам две функции для таких операций. Первая — функция gethostbyname, вторая — функция getaddrinfo. Microsoft рекомендует использовать getaddrinfo, учитывая при том, что она появилась в winsock 2. Радует и то, что функция не зависит от протокола (будь то IPv4 или IPv6).

Структура addrinfo

Специальная структура для функции getaddrinfo. Объявим так:

  paddrinfo = ^addrinfo;
  addrinfo = packed record
    ai_flags, ai_family, ai_sockettype, ai_protocol: integer;
    ai_addrlen: integer;
    ai_canonname: pchar;
    ai_addr: psockaddr;
    ai_next: paddrinfo;
  end;

И сразу пару переменных:

var
  aiHints: addrinfo;
  aiRes: paddrinfo;

Переменную aiHints заполним и передадим функции, таким образом мы укажем, что хотим получить в переменную aiRes, указатель на которую также передадим.
Теперь по частям:
ai_flags нам не пригодится, есть желание — читай на msdn.
ai_family, ai_sockettype, ai_protocol — это, думаю, знакомо. Семейство адресов (AF_INET мы указываем для IPv4, AF_INET6 для IPv6, также есть константы для netbios, инфракрасного порта и bluetooth адаптера), тип сокета (SOCK_STREAM для TCP протокола) и протокол (IPPROTO_TCP).
ai_addr — надеюсь, знакомая тебе структура типа sockaddr, а точнее указатель на неё. Здесь будет тот ip-адрес, который мы стремимся получить. Указатель именно на такую структуру мы передаём функции Connect, про которую можешь прочитать в предыдущем посте о том, как провести http-запрос на сокетах. ai_addrlen — размер полученной структуры ai_addr.
ai_canonname — «a canonical name for the host». У меня оно оказалось пустым.
Теперь про ai_next. «The getaddrinfo function aggregates all responses if more than one namespace provider returns information,» говорит msdn. То есть, если нам нужны другие варианты, а в данном случае они нам вряд ли нужны, то мы ходим по структурам, использую указатель ai_next, пока не наткнёмся на nil.

Функция getaddrinfo

Вот и нужная нам функция. Получение хоста может быть с помощью DNS (Domain Name System), файла hosts или других механизмов — функция не настолько низкоуровневая, то есть выдерживает все стандартные приоритеты. В стандартном модуле winsock я её не обнаружил, поэтому её нужно объявить:

function getaddrinfo(nodename, servname: PChar; hints: paddrinfo; var res: paddrinfo): integer;
  stdcall; external 'ws2_32.dll';

nodename — сюда пишем ‘parsers.info’, то есть доменное имя. servname — согласно msdn, название сервиса или номер порта. Подойдёт как ’80’, так и nil.
hints — наша структура aiHints. «Наставления» функции, мы указываем то, что желаем получить.
res — указатель на структуру addrinfo, в которой вдруг окажется результат.
Функция getaddrinfo в случае успешного выполнения возвращает 0, иначе — код ошибки. Например, 11001 — host not found.

Практика

Естественно, сначала нужно инициализировать winsock, про функцию WSAStartup я писал опять же здесь.

  FillChar(aiHints, sizeOf(aiHints), 0);
  aiHints.ai_family:=AF_INET;
  aiHints.ai_sockettype:=SOCK_STREAM;
  aiHints.ai_protocol:=IPPROTO_TCP;
  if getaddrinfo('parsers.info', nil, @aiHints, aiRes)=0 then
    writeln(ord(aiRes.ai_addr.sin_addr.S_un_b.s_b1),'.',
            ord(aiRes.ai_addr.sin_addr.S_un_b.s_b2),'.',
            ord(aiRes.ai_addr.sin_addr.S_un_b.s_b3),'.',
            ord(aiRes.ai_addr.sin_addr.S_un_b.s_b4))
  else
    writeln('socket error ', WSAGetLastError);

Этот нехитрый код выводит ip-адрес моего блога.

Вроде всё, кроме ссылки на скачивание работающего исходника-примера.

А тем временем Сан Саныч в своем блоге пытается облегчить жизнь программиста.

P.S. По поводу дальнейшего развития блога — планирую еще несколько постов про некоторые теоретические и практические аспекты winsock, также выложу один интересный модуль, над которым сейчас работаю. И, конечно, отчётно-обзорный пост про то, что было сделано, и про то, что планируется. Скучно не будет :)

Постовой: про запросы в интернет ты узнал, теперь узнай и про заработок в интернет