Добавить в цитаты Настройки чтения

Страница 125 из 399

Листинг 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 %sn", Sock_ntop((SA*)&servaddr, sizeof(servaddr)));

36   if (co

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

38   err_ret("co

39   close(sockfd);

40  }

41  if (*pptr == NULL)

42   err_quit("unable to co

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

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

45   Fputs(recvline, stdout);

46  }

47  exit(0);

48 }

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

29-35 Теперь мы пишем вызовы функций socket и co

36-39 Вызывается функция co

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

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

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

freebsd % <b>daytimetcpcli1 aix daytime</b>

trying 192.168.42.2:13

Sun Jul 27 22:44:19 2003

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

solaris % <b>daytimetcpcli1 gateway.tuc.noao.edu daytime</b>

trying 140.252.108.1:13