Предположим, что всякий раз, когда школьники хотят кому-нибудь передать информацию, они просто записывают ее на листах бумаги, вкладывают в самолетики, подписывают снаружи имя получателя и бросают их тому, кто расположен ближе к конечному адресату. Посредник смотрит на самолетик, видит назначенную цель и передает письмо следующему лицу. В конечном счете, адресат, которому предназначено сообщение, получит (точнее,
Хотите верьте, хотите нет, но такая схема практически точно отображает процесс функционирования компьютерных сетей[116]. Посредники здесь носят название маршрутизаторов, а самолетики называются пакетами, но в остальном все происходит именно так. Как и в жизни, некоторые из отправленных самолетиков (или пакетов) теряются. Если сообщение слишком длинное для одного пакета, его нужно распределить по нескольким пакетам (для каждого из которых есть шанс потеряться). Все школьники-посредники могут прочесть пакеты, если им захочется[117], и даже просто выбросить их вместо того, чтобы попытаться доставить их по адресу. При этом кто угодно может прервать ваш диалог, направив в него новые пакеты.
17.1.3. Как заставить реальность играть по точным правилам?
Встречаясь лицом к лицу с реальностью (миллионами бумажных самолетиков), разработчики протоколов прилагают все усилия для того, чтобы представлять сети по аналогии с телефонными линиями, а не со школьниками. Для описания сетевых протоколов установились разнообразные термины.
• Протоколы на основе логических соединений имеют две конечные точки подобно телефонным разговорам. Соединение должно быть установлено до начала передачи информации (ведь вы отвечаете на звонок словом "Алло!", а не начинаете сразу же разговаривать). Остальные пользователи не могут (и даже не должны иметь возможности) вторгаться в соединение. Протоколы, не имеющие таких характеристик, называются протоколами без установления соединения.
• Говорят, что протоколы обеспечивают упорядочение, если они гарантируют доставку данных в том же порядке, в котором они были отправлены.
• Протоколы предоставляют защиту от ошибок в том случае, если они автоматически отбрасывают поврежденные сообщения и подготавливаются к повторной передаче данных.
• Потоковые протоколы распознают только байтовые границы. Последовательности байтов могут разделяться и доставляться адресату по мере появления данных.
• Пакетные протоколы обрабатывают пакеты данных, сохраняя границы пакета и доставляя полные пакеты получателям. Пакетные протоколы, как правило, требуют определенного максимального размера пакета.
Хотя каждый из перечисленных атрибутов не зависит от остальных, в приложениях употребляются только два основных типа протоколов. Дейтаграммные протоколы являются механизмами пакетной передачи, не предоставляя при этом ни упорядочения, ни защиты от ошибок. Широко используется дейтаграммный протокол UDP, являющийся представителем семейства протоколов TCP/IP. Потоковые протоколы (такие как TCP из TCP/IP) — это протоколы потоковой передачи, которые обеспечивают и упорядочение, и защиту от ошибок.
Несмотря на то что дейтаграммные протоколы вроде UDP, несомненно, полезны[118], мы остановимся на применении потоковых протоколов, поскольку их легче использовать для большинства приложений. Подробное описание разработки протоколов и различий между их отдельными видами можно найти во многих книгах, например, [33] и [34].
17.1.4. Адреса
Поскольку каждый протокол поддерживает собственное определение сетевого адреса, интерфейс сокетов должен абстрагировать адреса. В качестве базовой формы адреса используется структура struct sockaddr
; его содержимое устанавливается по-разному для каждого семейства адресов. Передавая struct sockaddr
в системный вызов, процесс также указывает размер передаваемого адреса. Тип socklen_t
определяется как число, достаточно большое для хранения размера любого сокета, который используется системой.
Все типы struct sockaddr
соответствуют приведенному ниже определению.
#include
struct sockaddr {
unsigned short sa_family;
char sa_data[MAXSOCKADDRDATA];
}
Первые два байта (размер short
) указывают семейство адресов, к которому относится данный адрес. Перечень стандартных адресных семейств, используемых приложениями Linux, приведен в табл. 17.1.
Таблица 17.1. Семейства протоколов и адресов