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-37
msg_control
msg_control
38-41
msg_flags
unp_in_pktinfo
42-43
CMSG_FIRSTHDR
CMSG_NEXTHDR
47-54
55-63
Рис. 22.1. Объект вспомогательных данных, возвращаемый для параметра IP_RECVIF
Вспомните структуру адреса сокета канального уровня (см. листинг 18.1). Данные, возвращаемые в объекте вспомогательных данных, представлены в одной из этих структур, но длины трех элементов являются нулевыми (длина имени, адреса и селектора). Следовательно, нет никакой необходимости указывать эти значения, и таким образом структура имеет размер 8 байт, а не 20, как было в листинге 18.1. Возвращаемая нами информация — это индекс интерфейса.
Пример: вывод IP-адреса получателя и флага обрезки дейтаграммы
Для проверки нашей функции мы изменим функцию
dg_echo
recvfrom_flags
dg_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 char
mesg[MAXLINE], str[INET6_ADDRSTRLEN], ifname[IFNAMSIZ];
12 struct in_addr in_zero;
13 struct in_pktinfo pktinfo;
14 #ifdef IP_RECVDSTADDR
15 if (setsockopt(sockfd, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)) < 0)
16 err_ret("setsockopt of IP_RECVDSTADDR");
17 #endif
18 #ifdef IP_RECVIF
19 if (setsockopt(sockfd, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)) < 0)
20 err_ret("setsockopt of IP_RECVIF");
21 #endif
22 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_TRUNC
36 if (flags & MSG_TRUNC)
37 printf(" (datagram truncated)");
38 #endif
39 #ifdef MSG_CTRUNC
40 if (flags & MSG_CTRUNC)
41 printf(" (control info truncated)");
42 #endif
43 #ifdef MSG_BCAST
44 if (flags & MSG_BCAST)
45 printf(" (broadcast)");
46 #endif
47 #ifdef MSG_MCAST
48 if (flags & MSG_MCAST)
49 printf(" (multicast)");
50 #endif
51 printf("n");