UDP-сокет, присоединившийся к многоадресной группе, не должен "подключаться" к какому-либо адресу с помощью функции connect
или WSAConnect
. Соответственно, для отправки данных такой сокет может использовать только sendto
и WSASendTo
. Сокет, присоединившийся к группе, может отправлять данные на любой адрес, но если используется поддержка качества обслуживания, она работает только при отправке данных на групповой адрес сокета. Отправка данных на групповой адрес не требует присоединения к группе, причем для сокета, отправляющего данные, нет никакой разницы между отправкой данных на обычный адрес и на групповой. И в том и в другом случае используется функция sendto
или WSASendto
(или sendWSASend
с предварительным вызовом connect
). Никаких дополнительных действий для отправки данных на групповой адрес выполнять не требуется. Порт при этом также указывается. Как мы уже видели, номер порта при добавлении сокета в группу не указывается, но сам сокет перед этим должен быть привязан к какому-либо порту. При отправке группового сообщения его получат только те сокеты, входящие в группу, чей порт привязки совпадает с портом, указанным в адресе назначения сообщения.
Если сокет, отправляющий сообщение на групповой адрес, сам является членом этой группы, он, в зависимости от настроек, может получать или не получать свое сообщение. Это определяется его параметром IP_MULTICAST_LOOP
, имеющим тип BOOL
. По умолчанию этот параметр равен True
— это значит, что сокет будет получать свои собственные сообщения. С помощью функции setsockopt
можно изменить значение этого параметра на False
, и тогда сокет не будет принимать свои сообщения.
Параметром IP_MULTICAST_LOOP
следует пользоваться осторожно, т.к. он не поддерживается в Windows NT 4 и требует Windows 2000 или выше. В Windows 9x/МЕ он тоже не поддерживается (хотя упоминания об этом в MSDN нет).
В разд. 2.1.4 мы говорили, что каждый IP-пакет в своем заголовке имеет целочисленный параметр TTL (Time То Live). Его значение определяет, сколько маршрутизаторов может пройти данный пакет. По умолчанию групповые пакеты имеют TTL, равный 1, т.е. могут распространяться только в пределах непосредственно примыкающих подсетей. Целочисленный параметр сокета IP_MULTICAST_TTL
позволяет программе изменить это значение.
У функции WSAJoinLeaf
не предусмотрены параметры для задания адреса сетевого интерфейса, через который следует получать групповые сообщения, поэтому всегда используется интерфейс, выбираемый системой для этих целей по умолчанию. Выбрать интерфейс, который система будет назначать по умолчанию, можно с помощью параметра сокета IP_MULTICAST_IF
. Этот параметр имеет тип TSockAddr
, причем значимыми полями структуры в данном случае являются sin_family
и sin_addr
, а значение поля sin_port
игнорируется.
Значения констант IP_MULTICAST_IF
, IP_MULTICAST_TTL
и IP_MULTICAST_LOOP
также зависят от версии WinSock. В WinSock 1 они должны быть равны 2, и 4, а в WinSock 2 — 9, 10 и 11 соответственно.
2.2.12. Дополнительные функции
В этом разделе мы рассмотрим некоторые функции, относящиеся в WinSock к дополнительным. В WinSock 1 эти функции вместе со всеми остальными экспортируются библиотекой WSock32.dll, а в WinSock 2 они вынесены в отдельную библиотеку MSWSock.dll (в эту же библиотеку вынесены некоторые устаревшие функции типа EnumProtocols
).
Начнем мы знакомство с этими функциями с функции WSARecvEx
(которая, кстати, является расширенной версией функции recv
, а отнюдь не WSARecv
, как это можно заключить из ее названия), имеющей следующий прототип:
function WSARecvEx(s: TSocket; var buf; len: Integer; var flags: Integer): Integer;
Видно, что она отличается от обычной функции recv
только тем, что флаги передаются через параметр-переменную вместо значения. В функции WSARecvEx
этот параметр не только входной, но и выходной; функция может модифицировать его. Ранее мы познакомились с функцией WSARecv
, которая также может модифицировать переданные ей флаги, но условия, при которых эти две функции модифицируют флаги, различаются.
При использовании TCP (а также любого другого потокового протокола) флаги не изменяются функцией, и результат работы WSARecvEx
эквивалентен результату работы recv
.
Как мы уже не раз говорили, дейтаграмма UDP должна быть прочитана из буфера сокета целиком. Если в буфере, переданном функции recv
или recvfrom
, недостаточно места для получения дейтаграммы, эти функции завершаются с ошибкой. При этом в буфер помещается та часть дейтаграммы, которая может в нем поместиться, а оставшаяся часть дейтаграммы теряется. Функция WSARecvEx
отличается от recv
только тем, что в случае, когда размер буфера меньше размера дейтаграммы, она завершается без ошибки (возвращая при этом размер прочитанной части дейтаграммы, т.е. размер буфера) и добавляет флаг MSG_PARTIAL
к параметру flags
. Остаток дейтаграммы при этом также теряется. Таким образом, WSARecvEx
дает альтернативный способ проверки того, что дейтаграмма не поместилась в буфер, и в некоторых случаях этот способ может оказаться удобным.
Читать дальше
Конец ознакомительного отрывка
Купить книгу