Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Программное получение IP из DNS (http://forum.oszone.net/showthread.php?t=29619)

rarelang 03-07-2004 02:09 204959

Всем привет,

Я пишу сетевое приложение и недавно столкнулся со следующей проблемой. У меня есть следующий WinSock/BSD совместимый код:
Код:

signed int result;

#ifndef UNIX
WSADATA WSAData;

result = WSAStartup(MAKEWORD(1, 1), &WSAData);
if(result != 0)
{
ERRORLOG("Ошибка при инициализации системы WinSock");
throw (signed int) 1;
}
#endif

SMTPServer=socket(AF_INET, SOCK_STREAM, 0);

if(SMTPServer==INVALID_SOCKET)
{
ERRORLOG("Ошибка при создании socket объекта");
throw 2;
}

struct sockaddr_in SERVERAddress;

SERVERAddress.sin_family = AF_INET;
SERVERAddress.sin_addr.s_addr = inet_addr(SMTPIServerIP.c_str());
SERVERAddress.sin_port = htons(SMTPServerPort);

result=connect(SMTPServer,(struct sockaddr*)&SERVERAddress, sizeof(SERVERAddress));
if(result)
{
throw 3;
}

...

В данном фрагменте вызов inet_addr(SMTPIServerIP.c_str()) используется для превращения строки с IP адресом (объекта string с содержимым типа “127.0.0.1”) в in_addr.

Подскажите мне пожалуйста какие функции (не специфичные для Microsoft) я могу использовать для получения IP адреса из DNS имени.

Или же, подскажите мне пожалуйста как я могу настроить и создать SOCKET объект не имея IP адреса и располагая только DNS именем.

Заранее спасибо за любой ответ или ссылку на интересующий меня материал.


[s]Исправлено: hasherfrog, 10:29 5-07-2004[/s]

BrutalBit 03-07-2004 21:11 204960

Цитата:

Функции для работы с адресами и DNS

В этом разделе мы обсудим несколько функций, без которых можно написать учебный пример, но без которых вряд ли обойдётся реальная программа. Поскольку для идентификации хостов в Internet широко используются доменные имена, мы должны изучить механизм преобразования их в IP-адреса. Кроме того мы изучим несколько удобных вспомогательных функций.

IP-адреса принято записывать в виде четырёх чисел, разделённых точками. Для преобразования адреса, записанного в таком формате, в число и наоборот используется семейство функций inet_addr, inet_aton и inet_ntoa.

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int inet_aton(const char *cp, struct in_addr *in_p);
unsigned long int inet_addr(const char *cp);
char *inet_ntoa(struct in_addr in);

Функция inet_addr часто используется в программах. Она принимает строку и возвращает адрес (уже с сетевым порядком следования байтов). Проблема с этой функцией состоит в том, что значение -1, возвращаемое ею в случае ошибки, является в то же время корректным адресом 255.255.255.255 (широковещательный адрес). Вот почему сейчас рекомендуется использовать более новую функцию inet_aton (Ascii TO Network). Для обратного преобразования используется функция inet_ntoa (Network TO Ascii). Обе эти функции работают с адресами в сетевом формате. Обратите внимание, что в случае ошибки они возвращают 0, а не -1.

Для преобразования доменного имени в IP-адрес используется функция gethostbyname.

#include <netdb.h>
   
struct hostent *gethostbyname(const char *name);

Эта функция получает имя хоста и возвращает указатель на структуру с его описанием. Рассмотрим эту структуру более подробно.

struct hostent {
   char    *h_name;
   char    **h_aliases;
   int     h_addrtype;
   int     h_length;
   char    **h_addr_list;
};
#define h_addr h_addr_list[0]

   * h_name. Имя хоста.
   * h_aliases. Массив строк, содержащих псевдонимы хоста. Завершается значением NULL.
   * h_addrtype. Тип адреса. Для Internet-домена - AF_INET.
   * h_length. Длина адреса в байтах.
   * h_addr_list. Массив, содержащий адреса всех сетевых интерфейсов хоста. Завершается нулём. Обратите внимание, что байты каждого адреса хранятся с сетевым порядке, поэтому htonl вызывать не нужно.

Как видим, gethostbyname возвращает достаточно полную информацию. Если нас интересует адрес хоста, мы можем выбрать его из массива h_addr_list. Часто берут самый первый адрес (как мы видели выше, для ссылки на него определён специальный макрос h_addr). Для определения имени хоста по адресу используется функция gethostbyaddr. Вместо строки она получает адрес (в виде sockaddr) и возвращает указатель на ту же самую структуру hostent. Используя эти две функции, нужно помнить, что они сообщают об ошибке не так, как остальные: вместо указателя возвращается NULL, а расширенный код ошибки записывается в глобальную переменную h_errno (а не errno). Соответственно, для вывода диагностического сообщения следует использовать herror вместо perror.
ПРЕДУПРЕЖДЕНИЕ
Следует иметь в виду, что функции gethostbyname и gethostbyaddr возвращают указатель на статическую область памяти. Это означает, что каждое новое обращение к одной из этих функций приведёт к перезаписи данных, полученных при преыдущем обращении.

В заключение рассмотрим ещё одно семейство полезных функций - gethostname, getsockname и getpeername.

#include <unistd.h>

int gethostname(char *hostname, size_t size);

Функция gethostname используется для получения имени локального хоста. Далее его можно преобразовать в адрес при помощи gethostbyname. Это даёт нам способ в любой момент программно получить адрес машины, на которой выполняется наша программа, что может быть полезным во многих случаях.

#include <sys/socket.h>

int getpeername(int sockfd, struct sockaddr *addr, int *addrlen);

Функция getpeername позволяет в любой момент узнать адрес сокета на "другом конце" соединения. Она получает дескриптор сокета, соединённого с удалённым хостом, и записывает адрес этого хоста в структуру, на которую указывает addr. Фактическое количество записанных байт помещается по адресу addrlen (не забудьте записать туда размер структуры addr до вызова getpeername). Полученный адрес при необходимости можно преобразовать в строку, используя inet_ntoa или gethostbyaddr. Функция getsockname по назначению обратна getpeername и позволяет определить адрес сокета на "нашем конце" соединения.

hasherfrog 05-07-2004 10:48 204961

Одна из многочисленных по форме  (но однообразных по содержанию) вариаций:
Код:

unsigned long host_resolve (char *host)
{
  struct in_addr addr;
  struct hostent *host_ent;
 
  addr.s_addr = inet_addr (host);
  if (addr.s_addr == -1)
    {
      host_ent = gethostbyname (host);
      if (host_ent == NULL)
        addr.s_addr = 0;
      else
        bcopy (host_ent->h_addr, (char *)&addr.s_addr, host_ent->h_length);
    }
  return addr.s_addr;
}

bcopy - аналог memcpy

Добавлено:

Кстати, в QT есть клас QDns. Он занимается созданием и обновлением в памяти dns-базы (соответствий dhs и ip адресов). Что интересно, в исходниках присутствует код для виндов (чего вообще-то не должно было бы быть). Можете посмотреть.


Время: 03:04.

Время: 03:04.
© OSzone.net 2001-