Уильям Стивенс - UNIX: разработка сетевых приложений
- Название:UNIX: разработка сетевых приложений
- Автор:
- Жанр:
- Издательство:Питер
- Год:2007
- Город:Санкт-Петербург
- ISBN:5-94723-991-4
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
UNIX: разработка сетевых приложений - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
В Беркли-ядрах полученный маршрут от отправителя, так же как и другие параметры IP, никогда не возвращается для сокетов UDP. Показанный на с. 775 [128] код, предназначенный для получения параметров IP, существовал со времен 4.3BSD Reno, но так как он не работал, его всегда приходилось превращать в комментарий. Таким образом, для сокетов UDP невозможно использовать обращенный маршрут от отправителя полученной дейтаграммы, чтобы отослать ответ.
27.3. Параметры маршрута от отправителя IPv4
Маршрут от отправителя ( source route ) — это список IP-адресов, указанных отправителем дейтаграммы IP. Если маршрут является жестким ( строгим , strict), то дейтаграмма должна передаваться только между указанными узлами и пройти их все. Иными словами, все узлы, перечисленные в маршруте от отправителя, должны быть соседними друг для друга. Но если маршрут является свободным , или гибким ( loose ), дейтаграмма должна пройти все перечисленные в нем узлы, но может при этом пройти и еще какие-то узлы, не входящие в список.
Маршрутизация от отправителя (source routing) в IPv4 является предметом споров и сомнений. В [20] пропагандируется отказ от поддержки этой функции на всех маршрутизаторах, и многие организации и провайдеры действительно следуют этому принципу. Один из наиболее разумных способов использования маршрутизации от отправителя — это обнаружение с помощью программы traceroute асимметричных маршрутов, как показано на с. 108–109 [111], но в настоящее время даже этот способ становится непопулярен. Тем не менее определение и получение маршрута от отправителя — это часть API сокетов, и поэтому заслуживает описания.
Параметры IPv4, связанные с маршрутизацией от отправителя, называются параметрами маршрутизации от отправителя с записью (Loose Source and Record Routes — LSRR в случае свободной маршрутизации и Strict Source and Record Routes — SSRR в случае жесткой маршрутизации), так как при проходе дейтаграммы через каждый из перечисленных в списке узлов происходит замена указанного адреса на адрес интерфейса для исходящих дейтаграмм. Это позволяет получателю дейтаграммы обратить полученный список, превратив его в маршрут, по которому будет послан ответ отправителю. Примеры этих двух маршрутов от отправителя вместе с соответствующим выводом программы tcpdump
, приведены в разделе 8.5 книги [111].
Маршрут от отправителя мы определяем как массив адресов IPv4, которому предшествуют три однобайтовых поля, как показано на рис. 27.1. Это формат буфера, который передается функции setsockopt
.

Рис. 27.2. Формат параметра маршрута от отправителя, возвращаемого функцией getsockopt
В первую очередь, мы можем отметить, что порядок следования адресов изменен ядром на противоположный относительно полученного маршрута от отправителя. Имеется в виду следующее: если в полученном маршруте содержались адреса А, В, С и D в указанном порядке, то под противоположным порядком подразумевается следующий: D, С, В, А. Первые 4 байта содержат первый IP-адрес из списка, затем следует однобайтовый параметр NOP (для выравнивания), затем — 3-байтовый заголовок параметра маршрута от отправителя, и далее остальные IP-адреса. После 3-байтового заголовка может следовать до 9 IP-адресов, и максимальное значение поля len
в возвращенном заголовке равно 39. Поскольку параметр NOP всегда присутствует, длина буфера, возвращаемая функцией getsockopt
, всегда будет равна значению, кратному 4 байтам.
Формат, приведенный на рис. 27.2, определен в заголовочном файле в виде следующей структуры:
#define MAX_IPOPTLEN 40
struct ipoption {
struct in_addr ipopt_dst; /* адрес первого получателя */
char ipopt_list[MAX_IPOPTLEN]; /* соответствующие параметры */
};
В листинге 27.3 мы анализируем эти данные, не используя указанную структуру.
Возвращаемый формат отличается от того, который был передан функции setsockopt
. Если нам было бы нужно преобразовать формат, показанный на рис. 27.2, к формату, показанному на рис. 27.1, нам следовало бы поменять местами первые и вторые 4 байта и изменить значение поля len
, добавив к имеющемуся значению 4. К счастью, нам не нужно этого делать, так как Беркли-реализации автоматически используют обращенный маршрут от получателя для сокета TCP. Иными словами, данные, возвращаемые функцией getsockopt
(представленные на рис. 27.2), носят чисто информативный характер. Нам не нужно вызывать функцию setsockopt
, чтобы указать ядру на необходимость использования данного маршрута для дейтаграмм IP, отсылаемых по соединению TCP, — ядро сделает это само. Подобный пример с нашим сервером TCP мы вскоре увидим.
Следующей из рассматриваемых нами функций, связанных с параметром маршрутизации, полученный маршрут от отправителя передается в формате, показанном на рис. 27.2. Затем она выводит соответствующую информацию. Эту функцию inet_srtcrt_print
мы показываем в листинге 27.3.
Листинг 27.3. Функция inet_srtcrt_print: вывод полученного маршрута от отправителя
//ipopts/sourceroute.c
37 void
38 inet_srcrt_print(u_char *ptr, int len)
39 {
40 u_char c;
41 char str[INET_ADDRSTRLEN];
42 struct in_addr hop1;
43 memcpy(&hop1, ptr, sizeof(struct in_addr));
44 ptr += sizeof(struct in_addr);
45 while ((c = *ptr++) == IPOPT_NOP); /* пропуск параметров NOP */
46 if (с == IPOPT_LSRR)
47 printf("received LSRR: ");
48 else if (c == IPOPT_SSRR)
49 printf("received SSRR: ");
50 else {
51 printf("received option type %d\n", c);
52 return;
53 }
54 printf("%s ", Inet_ntop(AF_INET, &hop1, str, sizeof(str)));
55 len = *ptr++ - sizeof(struct in_addr); /* вычитаем адрес получателя */
56 ptr++; /* пропуск указателя */
57 while (len > 0) {
58 printf("%s ", Inet_ntop(AF_INET, ptr, str, sizeof(str)));
59 ptr += sizeof(struct in_addr);
60 len -= sizeof(struct in_addr);
61 }
62 printf("\n");
63 }
43-45
Первый IP-адрес в буфере сохраняется, а все следующие за ним параметры NOP мы пропускаем.
46-62
Мы выводим информацию о маршруте и проверяем значение поля code
, содержащегося в 3-байтовом заголовке, получаем значение поля len
и пропускаем указатель ptr
. Затем мы выводим все IP-адреса, следующие за 3-байтовым заголовком, кроме IP-адреса получателя.
Пример
Теперь мы модифицируем наш эхо-сервер TCP таким образом, чтобы выводить полученный маршрут от отправителя, а эхо-клиент TCP — так, чтобы маршрут от отправителя можно было задавать. В листинге 27.4 показан код эхо-клиента TCP.
Читать дальшеИнтервал:
Закладка: