Чтение ICMP-сообщений
Начнем с включаемых в программу файлов и функции main (листинг 4.3).
Листинг 4.3. Функция main программы icmp
icmp.с
1 #include <sys/types.h>
2 #include <netinet/in_systm.h>
3 #include <netinet/in.h>
4 #include <netinet/ip.h>
5 #include <netinet/ip_icmp.h>
6 #include <netinet/udp.h>
7 #include <etcp.h>
8 int main (int args, char **argv)
9 {
10 SOCKET s;
11 struct protoent *pp;
12 int rc;
13 char icmpdg [1024];
14 INIT ();
15 pp = getprotobyname (“icmp“);
16 if (pp == NULL)
17 error ( 1, errno, “ошибка вызова getprotobyname” );
18 s = socket (AF_INET, SOCK_RAW, pp->p_proto);
19 if (!isvalidsock (s))
20 error ( 1, errno, “ошибка вызова socket” );
21 for ( ; ; )
22 {
23 rc = recvform (s, icmpdg, sizeof (icmpdg)), 0,
24 NULL, NULL);
25 if ( rc < 0 )
26 error ( 1, errno, “ошибка вызова recvfrom” );
27 print_dg (icmpdg, rc);
28 }
29 }
Открытие простого сокета
15-20 Поскольку использован простой сокет, надо указать нужный протокол. Вызов фуекции getprotobyname возвращает структуру, содержащую номер протокола ICMP. Обратите внимание, что в качестве типа указана константа SOCK_RAW, а не SOCK_STREAM или SOCK_DGRAM, как раньше.
Цикл обработки событий
21-28 Читаем каждую IP-диаграмму, используя recvform, как и в случае UDP-датаграмм. Для печати поступающих ICMP-сообщений вызываем функцию print_dg.