Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
21 #endif
22 }
Пример
Сначала приведем пример с Ipv4:
freebsd % traceroute www.unpbook.com
traceroute to www.unpbook.com (206.168.112.219): 30 hops max. 24 data bytes
1 12.106.32.1 (12.106.32.1) 0.799 ms 0.719 ms 0.540 ms
2 12.124.47.113 (12.124.47.113) 1.758 ms 1.760 ms 1.839 ms
3 gbr2-p27.sffca.ip.att.net (12.123.195.38) 2.744 ms 2.575 ms 2.648 ms
4 tbr2-p012701.sffca.ip.att.net (12.122.11.85) 3.770 ms 3.689 ms 3.848 ms
5 gbr3-p50.dvmco.ip.att.net (12.122.2.66) 26.202 ms 26.242 ms 26.102 ms
6 gbr2-p20.dvmco.ip.att.net (12.122.5.26) 26 255 ms 26.194 ms 26.470 ms
7 gar2-p370.dvmco.ip.att.net (12.123.36.141) 26.443 ms 26.310 ms 26.427 ms
8 att-46.den.internap.ip.att.net (12.124.158.58) 26.962 ms 27.130 ms 27.279 ms
9 border10 ge3-0-bbnet2.den.pnap.net (216.52.40.79) 27.285 ms 27 293 ms 26.860 ms
10 coop-2.border10.den.pnap.net (216 52.42.118) 28.721 ms 28.991 ms 30.077 ms
11 199.45.130.33 (199.45.130.33) 29.095 ms 29.055 ms 29 378 ms
12 border-to-141-netrack.boulder.со.coop.net (207.174.144.178) 30.875 ms 29.747 ms 30.142 ms
13 linux.unpbook.com (206.168.112.219) 31.713 ms 31.573 ms 33.952 ms
Ниже приведен пример с IPv6. Для лучшей читаемости длинные строки разбиты.
freebsd % traceroute www.kame.net
traceroute to orange.kame.net (2001:200:0:4819:203:47ff:fea5:3085): 30 hops max, 24 data bytes
1 3ffe:b80:3:9ad1::1 (3ffe:b80:3:9ad1::1) 107.437 ms 99.341 ms 103.477 ms
2 Viagenie-gw.int.ipv6.ascc.net (2001:288:3b0::55)
105.129 ms 89.418 ms 90.016 ms
3 gw-Viagenie.int.ipv6.ascc.net (2001:288:3b0::54)
302.300 ms 291.580 ms 289.839 ms
4 c7513-gw.int.ipv6.ascc.net (2001:288:3b0::c)
296.088 ms 298.600 ms 292.196 ms
5 m160-c7513.int.ipv6.ascc.net (2001:288:3b0::1e)
296.266 ms 314.878 ms 302.429 ms
6 m20jp-ml60tw.int.ipv6.ascc.net (2001:288:3b0::1b)
327.637 ms 326.897 ms 347.062 ms
7 hitachi1.otemachi.wide.ad.jp (2001:200:0:1800::9c4:2)
420.140 ms 426.592 ms 422.756 ms
8 pc3.yagami.wide.ad.jp (2001:200:0:1c04::1000:2000)
415.471 ms 418.308 ms 461.654 ms
9 gr2000.k2c.wide.ad.jp (2001:200:0:8002::2000:1)
416.581 ms 422.430 ms 427.692 ms
10 2001:200:0:4819:203:47ff:fea5:3085 (2001:200:0:4819:203:47ff:fea5:3085)
417.169 ms 434.674 ms 424.037 ms
28.7. Демон сообщений ICMP
Получение асинхронных ошибок ICMP на сокет UDP всегда было и продолжает оставаться проблемой. Ядро получает сообщения об ошибках ICMP, но они редко доставляются приложениям, которым необходимо о них знать. Мы видели, что для получения этих ошибок в API сокетов требуется присоединение сокета UDP к одному IP-адресу (см. раздел 8.11). Причина такого ограничения заключается в том, что единственная ошибка, возвращаемая функцией recvfrom
, является целочисленным кодом errno
, а если приложение посылает дейтаграммы по нескольким адресам, а затем вызывает recvfrom
, то данная функция не может сообщить приложению, какая из дейтаграмм вызвала ошибку.
В данном разделе предлагается решение, не требующее никаких изменений в ядре. Мы предлагаем демон ICMP-сообщений icmpd
, который создает символьный сокет ICMPv4 и символьный сокет ICMPv6 и получает все ICMP-сообщения, направляемые к ним ядром. Он также создает потоковый сокет домена Unix, связывает его (при помощи функции bind
) с полным именем /tmp/icmpd
и прослушивает входящие соединения (устанавливаемые при помощи функции connect
) клиентов с этим сокетом. Схема соединений изображена на рис. 28.7.

Рис. 28.8. Приложение создает свой сокет UDP и доменный сокет Unix
Далее приложение «передает» свой UDP-сокет демону через соединение домена Unix, используя технологию передачи дескрипторов, как показано в разделе 15.7. Такой подход позволяет демону получить копию сокета, так что он может вызвать функцию getsockname
и получить номер порта, связанный с сокетом. На рис. 28.9 показана передача сокета.

37 Inet_ntop(AF_INET, &hip->ip_dst, dststr, sizeof(dststr)),
38 hip->ip_p);
39 if (hip->ip_p == IPPROTO_UDP) {
40 udp = (struct udphdr*)(buf + hlen1 + 8 + hlen2);
41 sport = udp->uh_sport;
42 /* поиск доменного сокета клиента, отправка заголовка */
43 for (i = 0; i = 0 &&
45 client[i].family == AF_INET &&
46 client[i].lport == sport) {
47 bzero(&dest, sizeof(dest));
48 dest.sin_family = AF_INET;
49 #ifdef HAVE_SOCKADDR_SA_LEN
50 dest.sin_len = sizeof(dest);
51 #endif
52 memcpy(&dest.sin_addr, &hip->ip_dst,
53 sizeof(struct in_addr));
54 dest.sin_port = udp->uh_dport;
55 icmpd_err.icmpd_type = icmp->icmp_type;
56 icmpd_err.icmpd_code = icmp->icmp_code;
57 icmpd_err.icmpd_len = sizeof(struct sockaddr_in);
58 memcpy(&icmpd_err.icmpd_dest, &dest, sizeof(dest));
59 /* преобразование кода и типа ICMP в значение errno */
60 icmpd_err.icmpd_errno = EHOSTUNREACH; /* по умолчанию */
61 if (icmp->icmp_type == ICMP_UNREACH) {
62 if (icmp->icmp_code == ICMP_UNREACH_PORT)
63 icmpd_err.icmpd_errno = ECONNREFUSED;
64 else if (icmp->icmp_code == ICMP_UNREACH_NEEDFRAG)
65 icmpd_err.icmpd_errno = EMSGSIZE;
66 }
67 Write(client[i].connfd, &icmpd_err, sizeof(icmpd_err));
68 }
69 }
70 }
71 }
72 return(--nready);
73 }
29-31
ICMP-сообщения, которые посылаются приложениям, — это сообщения о недоступности порта, превышении времени и завершении клиента (см. табл. 28.1).
34-42
Указатель hip
указывает на IP-заголовок, который возвращается сразу после заголовка ICMP. Это IP-заголовок дейтаграммы, вызвавшей ICMP-ошибку. Мы убеждаемся, что эта IP-дейтаграмма является UDP-дейтаграммой, а затем извлекаем номер UDP-порта из UDP-заголовка, следующего за IP-заголовком.
43-55
По всем структурам client
осуществляется поиск подходящего семейства адресов и порта. Если соответствие найдено, строится структура адреса сокета IPv4, которая содержит IP-адрес получателя и порт из UDP-дейтаграммы, вызвавшей ошибку.
56-70
Строится структура icmpd_err
, посылаемая клиенту через доменный сокет Unix. Тип и код сообщения ICMP сначала отображаются в значение errno
, как показано в табл. 28.1.
Ошибки ICMPv6 обрабатываются функцией readable_v6
, первая часть которой приведена в листинге 28.31. Обработка ошибок ICMPv6 аналогична коду, приведенному в листингах 28.7 и 28.16.
Листинг 28.31. Обработка полученной дейтаграммы ICMPv6, первая часть
//icmpd/readable_v6.c
1 #include "icmpd.h"
2 #include
3 #include
4 #include
5 #include
6 #ifdef IPV6
7 #include
8 #include
9 #endif
10 int
11 readable_v6(void)
12 {
13 #ifdef IPV6
14 int i, hlen2, icmp6len, sport;
15 char buf[MAXLINE];
16 char srcstr[INET6_ADDRSTRLEN], dststr[INET6_ADDRSTRLEN];
17 ssize_t n;
18 socklen_t len;
19 struct ip6_hdr *ip6, *hip6;
20 struct icmp6_hdr *icmp6;
21 struct udphdr *udp;
22 struct sockaddr_in6 from, dest;
23 struct icmpd_err icmpd_err;
24 len = sizeof(from);
25 n = Recvfrom(fd6, buf, MAXLINE, 0, (SA*)&from, &len);
26 printf("%d bytes ICMPv6 from %s:", n, Sock_ntop_host((SA*)&from, len));
27 icmp6 = (struct icmp6_hdr*)buf; /* начало заголовка ICMPv6 */
28 if ((icmp6len = n)
29 err_quit("icmp6len (%d)
Интервал:
Закладка: