Книги в продаже (аннотация + содержание + отрывок)

Й. Снейдер
ЭФФЕКТИВНОЕ ПРОГРАММИРОВАНИЕ TCP/IP. БИБЛИОТЕКА ПРОГРАММИСТА.
Цена: 123 р.

Источник: Издательский дом 'ПИТЕР'
Разделы: Компьютерные сети
Подробнее: Информация от издателя (открывается в новом окне)
Заказ: Оформление покупки (открывается в новом окне)
      Программирование TCP/IP может показаться очень простым, но это заблуждение. Многие программисты сталкиваются с тем, что написанное ими сетевое приложение недостаточно надежно. Часто причиной такого положения дел является неосторожное обращение с сетевыми протоколами. Поэтому основное внимание в данной книге уделено тонким вопросам функционирования семейства протоколов и способам работы с ними. Здесь изложены подтвержденные практикой советы, технические приемы и эвристические правила программирования TCP/IP для достижения максимальной производительности; показано, как избежать многих типичных ошибок. Каркас кода и библиотека функций дают возможность создавать приложения, не думая о низкоуровневых деталях. Основные идеи и концепции иллюстрируются многочисленными примерами. Вы станете лучше понимать внутреннее устройство TCP/IP и получите необходимые практические навыки работы с этим семейством протоколов.
     
     
     
     
      СОДЕРЖАНИЕ
     
     
      Предисловие
      Глава 1. Введение
      Некоторые термины
      Путеводитель по книге
      Архитектура клиент-сервер
      Элементы API сокетов
      Резюме
      Глава 2. Основы
      Совет 1. О необходимости различать протоколы, требующие и не требующие установления логического соединения
      Резюме
      Совет 2. О том, что такое подсети и CIDR
      Классы адресов
      Подсети
      Ограниченное вещание
      Вещание на сеть
      Вещание на подсеть
      Вещание на все подсети
      Бесклассовая междоменная маршрутизация - CIDR
      Текущее состояние организации подсетей и CIDR
      Резюме
      Совет 3. О том, что такое частные адреса и NAT
      Резюме
      Совет 4. О разработке и применении каркасов приложений
      Каркас TCP-сервера
      Каркас TCP-клиента
      Каркас UDP-сервера
      Каркас UDP-клиента
      Резюме
      Совет 5. О том, почему интерфейс сокетов лучше интерфейса XTI/TLI
      Резюме
      Совет 6. О том, что TCP - потоковый протокол
      Резюме
      Совет 7. О важности правильной оценки производительности TCP
      Источник и приемник на базе UDP
      Источник и приемник на базе TCP
      Резюме
      Совет 8. О том, что не надо заново изобретать TCP
      Резюме
      Совет 9. О том, что при всей надежности у TCP есть и недостатки
      Что такое надежность
      Потенциальные ошибки
      Сбой в сети
      Отказ приложения
      Крах хоста на другом конце соединения
      Резюме
      Совет 10. О том, что TCP не выполняет опрос соединения
      Механизм контролеров
      Пульсация
      Еще один пример пульсации
      Резюме
      Совет 11. О некорректном поведении партнера
      Проверка завершения работы клиента
      Проверка корректности входной информации
      Резюме
      Совет 12. О работе программы в локальной и глобальной сетях
      Недостаточная производительность
      Скрытая ошибка
      Резюме
      Совет 13. О функционировании протоколов
      Резюме
      Совет 14. О семиуровневой эталонной модели OSI
      Модель OSI
      Модель TCP/IP
      Резюме
      Глава 3. Создание эффективных и устойчивых сетевых программ
      Совет 15. Об операции записи в TCP
      Операция записи с точки зрения приложения
      Операция записи с точки зрения TCP
      Резюме
      Совет 16. О важности аккуратного размыкания TCP-соединений
      Вызов shutdown
      Аккуратное размыкание соединений
      Резюме
      Совет 17. О запуске приложения через inetd
      TCP-серверы
      UDP-серверы
      Резюме
      Совет 18. О назначении серверу номера порта с помощью tcpmux
      Резюме
      Совет 19. Об использовании двух TCP-соединений
      Архитектура с одним соединением
      Архитектура с двумя соединениями
      Резюме
      Совет 20. О том, как сделать приложение событийно-управляемым (1)
      Резюме
      Совет 21. О том, как сделать приложение событийно-управляемым (2)
      Резюме
      Совет 22. О том, что не надо прерывать состояние TIME-WAIT для закрытия соединения
      Что это такое
      Зачем нужно состояние TIME-WAIT
      Принудительная отмена состояния TIME-WAIT
      Резюме
      Совет 23. Об установке опции SO_REUSEADDR
      Резюме
      Совет 24. О написании одного большого блока вместо нескольких маленьких
      Отключение алгоритма Нейгла
      Запись со сбором
      Резюме
      Совет 25. Об организации тайм-аута для вызова connect
      Использование вызова alarm
      Использование select
      Резюме
      Совет 26. О вреде копирования данных
      Буферы в разделяемой памяти
      Система буферов в разделяемой памяти
      Реализация в UNIX
      Реализация в Windows
      Резюме
      Совет 27. Об обнулении структуры sockaddr_in
      Совет 28. О важности порядка байтов
      Резюме
      Совет 29. О том, что не стоит "зашивать" IP-адреса и номера портов в код
      Резюме
      Совет 30. О подсоединенном UDP-сокете
      Резюме
      Совет 31. О том, что C - не единственный язык программирования
      Резюме
      Совет 32. О значимости размеров буферов
      Резюме
      Глава 4. Инструменты и ресурсы
      Совет 33. Об использовании утилиты ping
      Резюме
      Совет 34. Об использовании программы tcpdump или аналогичного средства
      Как работает tcpdump
      Использование tcpdump
      Выходная информация, формируемая tcpdump
      Резюме
      Совет 35. О применении программы traceroute
      Как работает traceroute
      Программа tracert в системе Windows
      Резюме
      Совет 36. О преимуществах программы ttcp
      Резюме
      Совет 37. О работе с программой lsof
      Резюме
      Совет 38. Об использовании программы netstat
      Активные сокеты
      Интерфейсы
      Маршрутная таблица
      Статистика протоколов
      Программа netstat в Windows
      Резюме
      Совет 39. О средствах трассировки системных вызовов
      Преждевременное завершение
      Низкая производительность ttcp
      Резюме
      Совет 40. О создании и применении программы для анализа ICMP-сообщений
      Чтение ICMP-сообщений
      Печать ICMP-сообщений
      Резюме
      Совет 41. О пользе книг Стивенса
      "TCP/IP Illustrated"
      "UNIX Network Programming"
      Совет 42. О чтении текстов программ
      Резюме
      Совет 43. О том, что надо знать RFC
      Тексты RFC
      Совет 44. Об участии в конференциях Usenet
      Другие ресурсы, относящиеся к конференциям
      Приложение 1
      Вспомогательный код для UNIX
      Заголовочный файл etcp.h
      Функция daemon
      Функция signal
      Приложение 2
      Вспомогательный код для Windows
      Заголовочный файл skel.h
      Функции совместимости с Windows
      Литература
      Предметный указатель
     
     
     
     
      ОТРЫВОК
     
     
      Совет 2. Выясните, что такое подсети и CIDR
     
      Классы адресов
      Подсети
      Ограниченное вещание
      Вещание на сеть
      Вещание на подсеть
      Вещание на все подсети
      Бесклассовая междоменная маршрутизация - CIDR
      Текущее состояние организации подсетей и CIDR
      Резюме
      Длина IP-адреса (в версии IPv4) составляет 32 бита. Адреса принято записывать в десятичной нотации - каждый из четырех байт представляется одним десятичным числом, которые отделяются друг от друга точками. Так, адрес 0x11345678 записывается в виде 17.52.86.120. При записи адресов нужно учитывать, что в некоторых реализациях TCP/IP принято стандартное для языка C соглашение о том, что числа, начинающиеся с нуля, записываются в восьмеричной системе. В таком случае 17.52.86.120 - это не то же самое, что 017.52.86.120. В первом примере адрес сети равен 17, а во втором - 15.
      Классы адресов
      Адреса класса D используются для группового вещания, а класс E зарезервирован для будущих расширений. Остальные классы - A, B и C - предназначены для адресации отдельных сетей и хостов.
      Класс адреса определяется числом начальных единичных битов. У адресов класса A вообще нет бита 1 в начале, у адресов класса B - один такой бит, у адресов класса C - два и т.д. Идентификация класса адреса чрезвычайно важна, поскольку от этого зависит интерпретация остальных битов адреса.
      Остальные биты любого адреса классов A, B и C разделены на две группы. Первая часть любого адреса представляет собой идентификатор сети, вторая - идентификатор хоста внутри этой сети.
      Примечание Биты идентификации класса также считаются частью идентификатора сети. Так, 130.50.10.200 - это адрес класса B, в котором идентификатор сети равен 0x8232.
      Смысл разбивки адресного пространства на классы в том, чтобы обеспечить необходимую гибкость, не теряя адресов. Например, класс A позволяет адресовать сети с огромным (16777214) количеством хостов.
      Примечание Существует 224, или 16777216 возможных идентификаторов хостов, но адрес 0 и адрес, состоящий из одних единиц, имеют специальный смысл. Адрес из одних единиц - это широковещательный адрес. IP-датаграммы, посланные по этому адресу, доставляются всем хостам в сети. Адрес 0 означает "этот хост" и используется хостом как адрес источника, которому в ходе процедуры начальной загрузки необходимо определить свой истинный сетевой адрес. Поэтому число хостов в сети всегда равно 2n - 2, где n - число бит в части адреса, относящейся к хосту.
      Поскольку в адресах класса A под идентификатор сети отводятся 7 бит, то всего существует 128 сетей класса A.
      Примечание Как и в случае идентификаторов хостов, два из этих адресов зарезервированы. Адрес 0 означает "эта сеть" и, аналогично хосту 0, используется для определения адреса сети в ходе начальной загрузки. Адрес 127 - это адрес "собственной" сети хоста. Датаграммы, адресованные сети 127, не должны покидать хост-отправитель. Часто этот адрес называют "возвратным" (loopback) адресом, поскольку отправленные по нему датаграммы "возвращаются" на тот же самый хост.
      На другом полюсе располагаются сети класса C. Их очень много, но в каждой может быть не более 254 хостов. Таким образом, адреса класса A предназначены для немногих гигантских сетей с миллионами хостов, тогда как адреса класса C - для миллионов сетей с небольшим количеством хостов.
      В табл. 2.1 показано, сколько сетей и хостов может существовать в каждом классе, а также диапазоны допустимых адресов. Будем считать, что сеть 127 принадлежит классу A, хотя на самом деле она, конечно, недоступна для адресации.
      Таблица 2.1. Число сетей, хостов и диапазоны адресов для классов A, B и C
      Класс Сети Хосты Диапазон адресов
      A 127 16 777 214 0.0.0.1-127.255.255.255
      B 16 384 65 534 128.0.0.0-191.255.255.255
      C 2 097 252 254 192.0.0.0-223.255.255.255
      Первоначально проектировщики набора протоколов TCP/IP полагали, что сети будут исчисляться сотнями, а хосты - тысячами.
      Примечание В действительности, как отмечается в работе [Huitema 1995], в исходном проекте фигурировали только адреса, которые теперь относятся к классу A. Подразделение на три класса было сделано позже, чтобы иметь более 256 сетей.
      Появление дешевых, повсеместно применяемых персональных компьютеров привело к значительному росту числа сетей и хостов. Нынешний размер Internet намного превосходит ожидания его проектировщиков.
      Такой рост выявил некоторые недостатки классов адресов. Прежде всего, число хостов в классах A и B слишком велико. Вспомним, что идентификатор сети, как предполагалось, относится к физической сети, например локальной. Но никто не станет строить физическую сеть из 65000 хостов, не говоря уже о 16000000. Вместо этого большие сети разбиваются на сегменты, взаимосвязанные маршрутизаторами.
      В качестве простого примера рассмотрим два сегмента сети, изображенной на рис. 2.5.
      Если хосту H1 нужно обратиться к хосту H2, то он получает физический адрес, соответствующий IP-адресу H2 (используя для этого метод, свойственный данной реализации физической сети), и помещает датаграмму "на провод".
      А если хосту H1 необходимо обратиться к хосту H3? Напрямую послать датаграмму невозможно, даже если известен физический адрес получателя, поскольку H1 и H3 находятся в разных сетях. Поэтому H1 должен отправить датаграмму через маршрутизатор R1. Если у двух сегментов разные идентификаторы сетей, то H1 по своей маршрутной таблице определяет, что пакеты, адресованные сегменту 2, обрабатываются маршрутизатором R1, и отправляет ему датаграмму в предположении, что тот переправит ее хосту H3.
      Итак, можно назначить двум сегментам различные идентификаторы сети. Но есть и другие решения в рамках системы адресных классов. Во-первых, маршрутная таблица хоста H1 может содержать по одному элементу для каждого хоста в сегменте 2, который определит следующего получателя на пути к этому хосту - R1. Такая же таблица должна размещаться на каждом хосте в сегменте 1. Аналогичные таблицы, описывающие достижимость хостов из сегмента 1, следует поместить на каждом хосте из сегмента 2. Очевидно, такое решение плохо масштабируется при значительном количестве хос
      тов. Кроме того, маршрутные таблицы придется вести вручную, что очень скоро станет непосильной задачей для администратора. Поэтому на практике такое решение почти никогда не применяется.
      Во-вторых, можно реализовать ARP-прокси (proxy ARP) таким образом, чтобы R1 казался для хостов из сегмента 1 одновременно H3, H4 и H5, а для хостов из сегмента 2 - H1, H2 и R2.
      Примечание Агента ARP в англоязычной литературе еще называют promiscuous ARP (пропускающий ARP) или ARP hack (трюк ARP).
      Это решение годится только в случае, когда в физической сети используется протокол ARP (Address Resolution Protocol - протокол разрешения адресов) для отображения IP-адресов на физические адреса. В соответствии с ARP хост, которому нужно получить физический адрес, согласующийся с некоторым IP-адресом, должен послать широковещательное сообщение с просьбой хосту, обладающему данным IP-адресом, выслать свой физический адрес. ARP-запрос получают все хосты в сети, но отвечает только тот, IP-адрес которого совпадает с запрошенным.
      Если применяется агент ARP, то в случае, когда хосту H1 необходимо послать IP-датаграмму H3, физический адрес которого неизвестен, он посылает ARP- запрос физического адреса H3. Но H3 этот запрос не получит, поскольку находится в другой сети. Поэтому на запрос отвечает его агент - R1, сообщая свой собственный адрес. Когда R1 получает датаграмму, адресованную H3, он переправляет ее конечному адресату. Все происходит так, будто H3 и H1 находятся в одной сети.
      Как уже отмечалось, агент ARP может работать только в сетях, которые используют протокол ARP и к тому же имеют сравнительно простую топологию. Подумайте, что случится при наличии нескольких маршрутизаторов, соединяющих сегменты 1 и 2.
      Из вышесказанного следует, что общий способ организовать сети с несколькими сегментами - это назначить каждому сегменту свой идентификатор сети. Но у этого решения есть недостатки. Во-первых, при этом возможна потеря многих адресов в каждой сети. Так, если у любого сегмента сети имеется свой адрес класса B, то большая часть IP-адресов просто не будет использоваться.
      Во-вторых, маршрутная таблица любого узла, который направляет датаграммы напрямую в комбинированную сеть, должна содержать по одной записи для каждого сегмента. В указанном примере это не так страшно. Но вообразите сеть из нескольких сотен сегментов, а таких сетей может быть много. Понятно, что размеры маршрутных таблиц станут громадными.
      Примечание Эта проблема более серьезна, чем может показаться на первый взгляд. Объем памяти маршрутизаторов обычно ограничен, и нередко маршрутные таблицы размещаются в памяти специального назначения на сетевых картах. Реальные примеры отказа маршрутизаторов из-за роста маршрутных таблиц рассматриваются в работе [Huitema 1995].
      Обратите внимание, что эти проблемы не возникают при наличии хотя бы одного идентификатора сети. IP-адреса не остаются неиспользованными, поскольку при потребности в новых хостах можно всегда добавить новый сегмент. С другой стороны, так как имеется лишь один идентификатор сети, в любой маршрутной таблице необходима всего одна запись для отправки датаграмм любому хосту в этой сети.
      Подсети
      Мне хотелось найти решение, сочетающее два достоинства: во-первых, небольшие маршрутные таблицы и эффективное использование адресного пространства, обеспечиваемые единым идентификатором сети, во-вторых, простота маршрутизации, характерная для сетей, имеющих сегменты с разными идентификаторами сети. Желательно, чтобы внешние хосты "видели" только одну сеть, а внутренние - несколько сетей, по одной для каждого сегмента.
      Это достигается с помощью механизма подсетей. Идея очень проста. Поскольку внешние хосты для принятия решения о выборе маршрута используют только идентификатор сети, администратор может распределять идентификаторы хостов по своему усмотрению. Таким образом, идентификатор хоста - это закрытая структура, не имеющая вне данной сети интерпретации.
      Разделение на подсети осуществляется по следующему принципу. Одна часть идентификатора хоста служит для определения сегмента (то есть подсети), в состав которого входит хост, а другая - для идентификации конкретного хоста. Рассмотрим, например, сеть класса B с адресом 190.50.0.0. Можно считать, что третий байт адреса - это идентификатор подсети, а четвертый байт - номер хоста в этой подсети. На рис. 2.6а приведена структура адреса с точки зрения внешнего компьютера. Идентификатор хоста - это поле с заранее неизвестной структурой. На рис. 2.6б показано, как эта стру
      ктура выглядит изнутри сети. Вы видите, что она состоит из идентификатора подсети и номера хоста.
      В приведенном примере взят адрес класса B, и поле номера хоста выделено по границе байта. Но это необязательно. На подсети можно разбивать сети классов A, B и C и часто не по границе байта. С каждой подсетью ассоциируется маска подсети, которой определяется, какая часть адреса отведена под идентификаторы сети и подсети, а какая - под номер хоста. Так, маска подсети для примера, показанного на рис. 2.6б, будет 0xffffff00. В основном маска записывается в десятичной нотации (255.255.255.0), но если разбивка проходит не по границе байта, то удобнее первая форма.
     

Эффективное программирование TCP/IP. Библиотека программиста. / Й. Снейдер - СПб: Питер, 2002. - 320 с.

Экономика и управление | Право/a> | Бухгалтерский учет и налоги |