UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
61 cmptr->cmsg_len, cmptr->cmsg_level, cmptr->cmsg_type);62 }63 return(n);64 #endif /* HAVE_MSGHDR_MSG_CONTROL */65 }34-37msg_controlmsg_control38-41msg_flagsunp_in_pktinfo42-43CMSG_FIRSTHDRCMSG_NEXTHDR47-5455-63
Рис. 22.1. Объект вспомогательных данных, возвращаемый для параметра IP_RECVIF
Вспомните структуру адреса сокета канального уровня (см. листинг 18.1). Данные, возвращаемые в объекте вспомогательных данных, представлены в одной из этих структур, но длины трех элементов являются нулевыми (длина имени, адреса и селектора). Следовательно, нет никакой необходимости указывать эти значения, и таким образом структура имеет размер 8 байт, а не 20, как было в листинге 18.1. Возвращаемая нами информация — это индекс интерфейса.
Пример: вывод IP-адреса получателя и флага обрезки дейтаграммы
Для проверки нашей функции мы изменим функцию
dg_echorecvfrom_flagsdg_echoЛистинг 22.3. Функция dg_echo, вызывающая нашу функцию recvfrom_flags
//advio/dgechoaddr.c 1 #include "unpifi.h" 2 #undef MAXLINE 3 #define MAXLINE 20 /* устанавливаем новое значение, чтобы пронаблюдать обрезку дейтаграмм */ 4 void 5 dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen) 6 { 7 int flags; 8 const int on = 1; 9 socklen_t len;10 ssize_t n;11 charmesg[MAXLINE], str[INET6_ADDRSTRLEN], ifname[IFNAMSIZ];12 struct in_addr in_zero;13 struct in_pktinfo pktinfo;14 #ifdef IP_RECVDSTADDR15 if (setsockopt(sockfd, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)) < 0)16 err_ret("setsockopt of IP_RECVDSTADDR");17 #endif18 #ifdef IP_RECVIF19 if (setsockopt(sockfd, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)) < 0)20 err_ret("setsockopt of IP_RECVIF");21 #endif22 bzero(&in_zero, sizeof(struct in_addr)); /* IPv4-адрес, состоящий из одних нулей */23 for (;;) {24 len = clilen;25 flags = 0;26 n = Recvfrom_flags(sockfd, mesg, MAXLINE, &flags,27 pcliaddr, &len, &pktinfo);28 printf("%d-byte datagram from %s", n, Sock_ntop(pcliaddr, len));29 if (memcmp(&pktinfo.ipi_addr, &in_zero, sizeof(in_zero)) != 0)30 printf(", to %s", Inet_ntop(AF_INET, &pktinfo.ipi_addr,31 str, sizeof(str)));32 if (pktinfo.ipi_ifindex > 0)33 printf(", recv i/f = %s",34 If_indextoname(pktinfо.ipi_ifindex, ifname));35 #ifdef MSG_TRUNC36 if (flags & MSG_TRUNC)37 printf(" (datagram truncated)");38 #endif39 #ifdef MSG_CTRUNC40 if (flags & MSG_CTRUNC)41 printf(" (control info truncated)");42 #endif43 #ifdef MSG_BCAST44 if (flags & MSG_BCAST)45 printf(" (broadcast)");46 #endif47 #ifdef MSG_MCAST48 if (flags & MSG_MCAST)49 printf(" (multicast)");50 #endif51 printf("n");
