Книга: UNIX: разработка сетевых приложений

Пример: вывод IP-адреса получателя и флага обрезки дейтаграммы

Пример: вывод IP-адреса получателя и флага обрезки дейтаграммы

Для проверки нашей функции мы изменим функцию dg_echo (см. листинг 8.2) так, чтобы она вызывала функцию recvfrom_flags вместо функции recvfrom. Новая версия функции dg_echo показана в листинге 22.3.

Листинг 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_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");
52   Sendto(sockfd, mesg, n, 0, pcliaddr, len);
53  }
54 }

Изменение MAXLINE

2-3 Мы удаляем существующее определение MAXLINE, имеющееся в нашем заголовочном файле unp.h, и задаем новое значение — 20. Это позволит нам увидеть, что произойдет, когда мы получим дейтаграмму UDP, превосходящую размер буфера, переданного функции (в данном случае функции recvmsg).

Установка параметров сокета IP_RECVDSTADDR и IP_RECVIF

14-21 Если параметр сокета IP_RECVDSTADDR определен, мы включаем его. Аналогично включается параметр сокета IP_RECVIF.

Чтение дейтаграммы, вывод IP-адреса отправителя и порта

24-28 Дейтаграмма читается с помощью вызова функции recvfrom_flags. IP-адрес отправителя и порт ответа сервера преобразуются в формат представления функцией sock_ntop.

Вывод IP-адреса получателя

29-31 Если возвращаемый IP-адрес ненулевой, он преобразуется в формат представления функцией inet_ntop и выводится.

Вывод имени интерфейса, на котором была получена дейтаграмма

32-34 Если индекс интерфейса ненулевой, его имя будет возвращено функцией if_indextoname. Это имя наша функция печатает на экране.

Проверка различных флагов

35-51 Мы проверяем четыре дополнительных флага и выводим сообщение, если какие-либо из них установлены.

Оглавление книги


Генерация: 1.300. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз