Пример: использование функций gethostbyname и getservbyname

Пример: использование функций gethostbyname и getservbyname

Теперь мы можем изменить код нашего TCP-клиента времени и даты, показанный в листинге 1.1, так, чтобы использовать функции gethostbyname и getservbyname и принимать два аргумента командной строки: имя узла и имя службы. Наша программа показана в листинге 11.2. Эта программа также демонстрирует желательное поведение при установлении соединения со всеми IP-адресами сервера на узле, имеющем несколько сетевых интерфейсов: попытки продолжаются до тех пор, пока соединение не будет успешно установлено или пока не будут перебраны все адреса.

Листинг 11.2. Наш клиент времени и даты, использующий функции gethostbyname и getservbyname

//names/daytimetcpcli1.c

 1 #include "unp.h"

 2 int

 3 main(int argc, char **argv)

 4 {

 5  int sockfd, n;

 6  char recvline[MAXLINE + 1];

 7  struct sockaddr_in servaddr;

 8  struct in_addr **pptr;

 9  struct in_addr *inetaddrp[2];

10  struct in_addr inetaddr;

11  struct hostent *hp;

12  struct servent *sp;

13  if (argc != 3)

14   err_quit("usage: daytimetcpcli1 <hostname> <service>");

15  if ((hp = gethostbyname(argv[1])) == NULL) {

16   if (inet_aton(argv[1], &inetaddr) == 0) {

17    err_quit("hostname error for %s: %s", argv[1],

18    hstrerror(h_errno));

19   } else {

20    inetaddrp[0] = &inetaddr;

21    inetaddrp[1] = NULL;

22    pptr = inetaddrp;

23   }

24  } else {

25   pptr = (struct in_addr**)hp->h_addr_list;

26  }

27  if ((sp = getservbyname(argv[2], "tcp")) == NULL)

28   err_quit("getservbyname error for %s", argv[2]);

29  for (; *pptr != NULL; pptr++) {

30   sockfd = Socket(AF_INET, SOCK_STREAM, 0);

31   bzero(&servaddr, sizeof(servaddr));

32   servaddr.sin_family = AF_INET;

33   servaddr.sin_port = sp->s_port;

34   memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));

35   printf("trying %s ", Sock_ntop((SA*)&servaddr, sizeof(servaddr)));

36   if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) == 0)

37    break; /* успешное завершение */

38   err_ret("connect error");

39   close(sockfd);

40  }

41  if (*pptr == NULL)

42   err_quit("unable to connect");

43  while ((n = Read(sockfd, recvline, MAXLINE)) > 0) {

44   recvline[n] = 0; /* null terminate */

45   Fputs(recvline, stdout);

46  }

47  exit(0);

48 }

Вызов функций gethostbyname и getservbyname

13-28 Первый аргумент командной строки — это имя узла, передаваемое в качестве аргумента функции gethostbyname, а второй — имя службы, передаваемое в качестве аргумента функции getservbyname. Наш код подразумевает использование протокола TCP, что мы указываем во втором аргументе функции getservbyname. Если функции gethostbyname не удается найти нужное имя, мы вызываем функцию inet_aton (см. раздел 3.6), чтобы проверить, не является ли аргумент командной строки IP-адресом в формате ASCII. В этом случае формируется список из одного элемента — этого IP-адреса.

Перебор всех адресов

29-35 Теперь мы пишем вызовы функций socket и connect в цикле, который выполняется для каждого адреса сервера, пока попытка вызова функции connect не окажется успешной или пока не закончится список серверов. После вызова функции socket мы заполняем структуру адреса сокета Интернета IP-адресом и номером порта сервера. Хотя в целях увеличения производительности мы могли бы вынести из цикла вызов функции bzero и последующие два присваивания, наш код легче читать в таком виде, как он представлен сейчас. Установление соединения с сервером редко является основным источником проблем с производительностью сетевого клиента.

Вызов функции connect

36-39 Вызывается функция connect, и если вызов оказывается успешным, функция break завершает цикл. Если установить соединение не удается, мы выводим сообщение об ошибке и закрываем сокет. Вспомните, что дескриптор, для которого вызов функции connect оказался неудачным, не может больше использоваться и должен быть закрыт.

Завершение программы

41-42 Если цикл завершается, потому что ни один вызов функции connect не закончился успехом, программа завершает работу.

Чтение ответа сервера

43-47 Мы считываем ответ сервера и завершаем программу, когда сервер закрывает соединение.

Если мы запустим эту программу, указав один из наших узлов, на котором работает сервер времени и даты, мы получим ожидаемый результат:

freebsd % daytimetcpcli1 aix daytime

trying 192.168.42.2:13

Sun Jul 27 22:44:19 2003

Но еще интереснее запустить программу, обратившись к маршрутизатору с несколькими сетевыми интерфейсами, на котором не работает сервер времени и даты:

solaris % daytimetcpcli1 gateway.tuc.noao.edu daytime

trying 140.252.108.1:13

connect error: Operation timed out

trying 140.252.1.4:13

connect error: Operation timed out

trying 140.252.104.1:13

connect error: Connection refused

unable to connect

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Использование функций

Из книги Excel. Мультимедийный курс автора Мединов Олег

Использование функций Программа Excel содержит огромное количество функций: математических, статистических, инженерных, логических, текстовых, финансовых и т. д. Эти функции вы можете использовать для создания формул или обработки данных таблицы.В данном разделе действие


Правило 30: Тщательно обдумывайте использование встроенных функций

Из книги Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ автора Мейерс Скотт

Правило 30: Тщательно обдумывайте использование встроенных функций Встроенные функции – какая замечательная идея! Они выглядят подобно функциям, они работают подобно функциям, они намного лучше макросов (см. правило 2). Их можно вызывать, не опасаясь накладных расходов,


ГЛАВА 2 Использование файловой системы и функций символьного ввода/вывода Windows

Из книги Системное программирование в среде Windows автора Харт Джонсон М

ГЛАВА 2 Использование файловой системы и функций символьного ввода/вывода Windows Нередко самыми первыми средствами операционной системы (ОС), с которыми разработчик сталкивается в любой системе, являются файловая система и простой терминальный ввод/вывод. Ранние ОС для PC,


17.8.3. Пример поиска информации хоста с использованием унаследованных функций

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.

17.8.3. Пример поиска информации хоста с использованием унаследованных функций Ниже приводится пример программы, использующей inet_aton(), inet_ntoa(), gethostbyname(), gethostbyaddr(). Она принимает единственный аргумент, который может быть либо именем хоста, либо IP-адресом в десятичном


Использование функций в операторах присваивания

Из книги VBA для чайников автора Каммингс Стив

Использование функций в операторах присваивания Поскольку функции и создаваемые вами процедуры типа Function возвращают значения, их тоже можно использовать в операторах присваивания. Например:ctrFavorite = InputBox(Кто сегодня фаворит?)В данном случае используется функция VBA Input Box,


Использование в scoqe встроенных функций

Из книги Самоучитель работы на Macintosh автора Скрылина Софья

Использование в scoqe встроенных функций Независимо от того, пишете ли вы собственную функцию или процедуру Sub, не стесняйтесь призывать на помощь широчайшие возможности встроенных функций Excel по анализу данных и проведению вычислений. Использовать их в своем собственном


5.2.7. Использование функций в формулах

Из книги Linux: Полное руководство автора Колисниченко Денис Николаевич

5.2.7. Использование функций в формулах Функцией называется операция, используемая в формуле, которая производит какие-либо действия с содержимым ячеек: вычисления, манипуляции с датами, со строками текста и т. п. Numbers включает 168 функций.Каждая функция состоит из имени и


27.3.4. Функция gethostbyname()

Из книги Linux программирование в примерах автора Роббинс Арнольд

27.3.4. Функция gethostbyname() Пользователям обычно удобнее указать символьное имя сервера, чем его IP-адрес. Для разрешения имени служит функция gethostbyname(). Вот ее прототип:#include <netinet/in.h>#include <netdb.h>struct hostent *gethostbyname(char *name);Данная функция возвращает указатель на структуру типа


9.1.6.2. Использование функций BSD: wait3() и wait4()

Из книги Linux и UNIX: программирование в shell. Руководство разработчика. автора Тейнсли Дэвид

9.1.6.2. Использование функций BSD: wait3() и wait4() Системные вызовы BSD wait3() и wait4() полезны, если вы интересуетесь ресурсами, использованными порожденным процессом. Функции нестандартны (что означает, что они не являются частью POSIX), но широко доступны, в том числе на GNU/Linux. Объявления


ИЗУЧЕНИЕ И ИСПОЛЬЗОВАНИЕ ФУНКЦИЙ printf( ) И scanf( )

Из книги автора

ИЗУЧЕНИЕ И ИСПОЛЬЗОВАНИЕ ФУНКЦИЙ printf( ) И scanf( )      Функции printf( ) и scanf( ) дают нам возможность взаимодействовать с программой. Мы называем их функциями ввода-вывода. Это не единственные функции, которыми мы можем воспользоваться для ввода и вывода данных с помощью


11.3. Функция gethostbyname

Из книги автора

11.3. Функция gethostbyname Узлы компьютерных сетей мы обычно идентифицируем по их именам, удобным для человеческого восприятия. Но во всех примерах книги специально использовались IP-адреса вместо имен, поэтому мы точно знаем, что входит в структуры адресов сокетов для таких


11.5. Функции getservbyname и getservbyport

Из книги автора

11.5. Функции getservbyname и getservbyport Службы, как и узлы, также часто идентифицируются по именам. Используя в нашем коде имя службы вместо номера порта, при условии, что имена служб сопоставляются номерам портов в некотором файле (обычно /etc/services), мы получаем следующее преимущество.


Использование функций sigsetjmp и siglongjmp

Из книги автора

Использование функций sigsetjmp и siglongjmp Нашу проблему можно решить корректно, если отказаться от прерывания блокированного системного вызова обработчиком сигнала, вместо этого вызвав из обработчика сигнала функцию siglongjmp. Этот метод называется нелокальным оператором goto