О чём не пишут в книгах по Delphi
Шрифт:
2.1.5. Протокол UDP
Протокол UDP (User Datagram Protocol — протокол пользовательских дейтаграмм) встречается реже, чем его "одноклассник" TCP, но он проще для понимания, поэтому мы начнем изучение транспортных протоколов с него. Коротко UDP можно описать как ненадежный протокол без соединения, основанный на дейтаграммах. Теперь рассмотрим каждую из этих характеристик подробнее.
UDP не имеет никаких исполнительных средств управления пакетами по сравнению с IP. Это значит, что пакеты, отправленные с помощью UDP, могут теряться, дублироваться и менять порядок следования. В сети без маршрутизаторов ничего этого с пакетами почти никогда не происходит, и UDP может условно считаться надежным протоколом. Сети с маршрутизаторами строятся, конечно же, таким образом, чтобы
Все сказанное отнюдь не означает, что на основе UDP нельзя построить надежный обмен данными, просто заботу об этом должно взять на себя само приложение. Каждый исходящий пакет должен содержать порядковый номер, и в ответ на него должен приходить специальный пакет — квитанция, которая уведомляет отправителя, что пакет доставлен. При отсутствии квитанции пакет высылается повторно (для этого необходимо ввести тайм-ауты на получение квитанции). Принимающая сторона по номерам пакетов восстанавливает их исходный порядок.
UDP не поддерживает соединение. Это означает, что при использовании этого протокола можно в любой момент отправить данные по любому адресу без необходимости каких-либо предварительных действий, направленных на установление связи с адресатом. Это напоминает процесс отправки обычного письма: на нем пишется адрес, и оно опускается в почтовый ящик без каких-либо предварительных действий. Такой подход обеспечивает большую гибкость, но лишает систему возможности автоматической проверки исправности канала связи.
Дейтаграммами называются пакеты, которые передаются как единое целое. Каждый пакет, отправленный с помощью UDP, составляет одну дейтаграмму. Принятые дейтаграммы складываются в буфер принимающего сокета и могут быть получены только раздельно: за одну операцию чтения из буфера программа, использующая сокет, может получить только одну дейтаграмму. Если в буфере лежит несколько дейтаграмм, потребуется несколько операций чтения, чтобы прочитать все. Кроме того, одну дейтаграмму нельзя получить из буфера по частям: она должна быть прочитана целиком за одну операцию. Чтобы данные, передаваемые разным сокетам, не перемешивались, каждый сокет должен получить уникальный в пределах узла номер от 0 до 65 535, называемый номером порта. При отправке дейтаграммы отправитель указывает IP-адрес и порт получателя, и система принимающей стороны находит сокет, привязанный к указанному порту, и помещает данные в его буфер. По сути дела, UDP является очень простой надстройкой над IP, все функции которой заключаются в том, что физический поток разделяется на несколько логических с помощью портов, и добавляется проверка целостности данных с помощью контрольной суммы (сам по себе протокол IP не гарантирует отсутствия искажений данных при передаче).
Максимальный размер одной дейтаграммы IP равен 65 535 байтам. Из них не менее 20 байтов занимает заголовок IP. Заголовок UDP имеет размер 8 байтов. Таким образом, максимальный размер одной дейтаграммы UDP составляет 65 507 байтов.
Типичная область применения UDP — программы, для которых потеря пакетов некритична. Например, некоторые сетевые 3D-игры в локальной сети используют UDP, т.к. очень часто посылают пакеты, информирующие о действиях игрока, и потеря одного пакета не приведет к существенным проблемам: следующий пакет доставит необходимые данные. Достоинства UDP — простота установления связи, возможность обмена данными с несколькими адресами через один сокет и отсутствие необходимости возобновлять соединение после разрыва связи. В некоторых задачах также очень удобно то, что дейтаграммы не смешиваются, и получатель всегда знает, какие данные были отправлены одной дейтаграммой, а какие — разными.
Еще одно преимущество UDP — возможность отправки широковещательных дейтаграмм. Для этого нужно указать широковещательный IP-адрес (обычно 255.255.255.255, но в некоторых случаях допустимы адреса типа 192.168.100.225
2.1.6. Протокол TCP
Протокол TCP (Transmission Control Protocol — протокол управления передачей) является надежным потоковым протоколом с соединением, т.е. полной противоположностью UDP. Единственное, что у этих протоколов общее, — это способ адресации: в TCР каждому сокету также назначается уникальный номер порта. Уникальность номера порта требуется только в пределах протокола: два сокета могут иметь одинаковые номера портов, если один из них работает через TCP, а другой через UDP.
В TCP предусмотрены так называемые хорошо известные (well-known) порты, которые зарезервированы для нужд системы и не должны использоваться программами. Стандарт TCP определяет диапазон хорошо известных портов от 0 до 255, в Windows и в некоторых других системах этот диапазон расширен до 0–1023. Часть портов UDP тоже выделена для системных нужд, но зарезервированного диапазона в UDP нет. Кроме того, некоторые системные утилиты используют порты за пределами диапазона 0–1023. Полный список системных портов для TCP и UDP содержится в MSDN, в разделе Resource Kits/Windows 2000 Server Resource Kit/TCP/IP Core Networking Appendixes/TCP and UDP Port Assignment.
Для отправки пакета с помощью TCP отправителю необходимо сначала установить соединение с получателем. После выполнения этого действия соединенные таким образом сокеты могут использоваться только для отправки сообщений друг другу. Если соединение разрывается (самой программой из-за проблем в сети), эти сокеты уже непригодны для установления нового соединения: они должны быть уничтожены, а вместо них созданы новые сокеты.
Механизм соединения, принятый в TCP, подразумевает разделение ролей соединяемых сторон: одна из них пассивно ждет, когда кто-то установит с ней соединение, и называется сервером, другая самостоятельно устанавливает соединение и называется клиентом. Действия клиента по установке связи заключаются в следующем: создать сокет, привязать его к адресу и порту вызвать функцию для установки соединения, передав ей адрес сервера. Если все эти операции выполнены успешно, то связь установлена, и можно начинать обмен данными. Действия сервера выглядят следующим образом: создать сокет, привязать его к адресу и порту, перевести в режим ожидания соединения и дождаться соединения. При соединении система создаст на стороне сервера специальный сокет, который будет связан с соединившимся клиентом, и обмениваться данными с подключившимся клиентом сервер будет через этот новый сокет. Старый сокет останется в режиме ожидания соединения. и другой клиент сможет к нему подключиться. Для каждого нового подключения будет создаваться новый сокет, обслуживающий только данное соединение, а исходный сокет будет по-прежнему ожидать соединения. Это позволяет нескольким клиентам одновременно соединяться с одним сервером, а серверу — не путаться в своих клиентах. Точное число клиентов, которые могут одновременно работать с сервером, в документации не приводится, но оно достаточно велико.
Установление такого соединения позволяет осуществлять дополнительный контроль прохождения пакетов. В рамках протокола TCP выполняется проверка доставки пакета, соблюдения очередности и отсутствия дублей. Механизмы обеспечения надежности достаточно сложны, и мы их здесь рассматривать не будем. Программисту для начала достаточно знать, что данные, переданные с помощью TCP, не теряются, не дублируются и доставляются в том порядке, в каком были отправлены. В противном случае отправитель получает сообщение об ошибке. Соединенные сокеты время от времени обмениваются между собой специальными пакетами, чтобы убедиться в наличии соединения.