Вход/Регистрация
UNIX: разработка сетевых приложений
вернуться

Стивенс Уильям Ричард

Шрифт:

15 err_quit("usage: daytimetcpcli3 <hostname> <service>");

16 if ((hp = gethostbyname(argv[1])) == NULL)

17 err_quit("hostname error for %s: %s", argv[1], hstrerror(h_errno));

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

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

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

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

22 sockfd = Socket(hp->h_addrtype, SOCK_STREAM, 0);

23 if (hp->h_addrtype == AF_INET) {

24 sa = (SA*)&servaddr;

25 salen = sizeof(servaddr);

26 } else if (hp->h_addrtype == AF_INET6) {

27 sa = (SA*)&servaddr6;

28 salen = sizeof(servaddr6);

29 } else

30 err_quit("unknown addrtype %d", hp->h_addrtype);

31 bzero(sa, salen);

32 sa->sa_family = hp->h_addrtype;

33 sock_set_port(sa, salen, sp->s_port);

34 sock_set_addr(sa, salen, *pptr);

35 printf("trying %s\n", Sock_ntop(sa, salen));

36 if (connect(sockfd, sa, salen) == 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; /* завершающий нуль */

45 Fputs(recvline, stdout);

46 }

47 exit(0);

48 }

Используем значение

h_addrtype
, возвращаемое функцией
gethostbyname
, для определения типа адреса. Также используем функции
sock_set_port
и
sock_set_addr
(см. раздел 3.8), чтобы установить два соответствующих поля в структуре адреса сокета.

Эта программа работает, однако имеется два ограничения. Во-первых, мы должны обрабатывать все различия, следя за

h_addrtype
и задавая соответствующим образом
sa
или
salen
. Более удачным решением было бы иметь библиотечную функцию, которая не только просматривает имя узла и имя службы, но и заполняет всю структуру адреса сокета (например,
getaddrinfo
, см. раздел 11.6). Во-вторых, эта программа компилируется только на узлах с поддержкой IPv6. Чтобы ее можно было откомпилировать на узле, поддерживающем только IPv4, следует добавить в код огромное количество директив
#ifdef
, что, несомненно, усложнит программу.

11.7. Разместите в памяти большой буфер (превышающий по размеру любую структуру адреса сокета) и вызовите функцию

getsockname
. Третий аргумент является аргументом типа «значение-результат», возвращающим фактический размер адресов протоколов. К сожалению, это допускают только структуры адреса сокета с фиксированной длиной (IPv4 и IPv6). Нет гарантии, что этот буфер будет работать с протоколами, которые могут вернуть структуру адреса сокета переменной длины (доменные сокеты Unix, см. главу 15).

11.8. Сначала размещаем в памяти массивы, содержащие имя узла и имя службы:

char host[NI_MAXHOST], serv[NI_MAXSERV];

После того как функция

accept
возвращает управление, вызываем вместо функции
sock_ntop
функцию
getnameinfo
:

if (getnameinfo(cliaddr, len, host, NI_MAXHOST, serv, NI_MAXSERV,

NI_NUMERICHOST | NI_NUMERICSERV) == 0)

printf("connection from %s.%s\n", host, serv);

  • Читать дальше
  • 1
  • ...
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: