end;
Поле IMR_MultiAddr
задает групповой адрес, к которому присоединяется сокет. У этой структуры должны быть заполнены поля sin_family
(значением AF_INET
) и sin_addr
. Номер порта здесь указывать не нужно, значение этого поля игнорируется. Поле IMR_Interface
определяет адрес сетевого интерфейса, через который будет вестись прием многоадресной рассылки. Если программу устраивает интерфейс, выбираемый системой по умолчанию, значение поля IMR_Interface.sin_addr
должно быть INADDR_ANY
(на компьютерах с одним сетевым интерфейсом обычно используется именно это значение). Но если у компьютера несколько сетевых интерфейсов, которые связывают его с разными сетями, интерфейс для получения групповых пакетов, выбираемый системой по умолчанию, может быть связан не с той сетью, из которой они реально ожидаются. В этом случае программа может явно указать IP-адрес того интерфейса, через который данный сокет должен принимать групповые пакеты. Как и в поле IMR_MultiAddr
, в поле IMR_Interface
задействованы только поля sin_familу
и sin_addr
, а остальные поля игнорируются.
Для прекращения членства сокета в группе служит та же функция setsockopt
, но с параметром IP_DROP_MEMBERSHIP
. Через параметр optval
при этом также передается структура ip_mreq
, значимые поля которой должны быть заполнены так же, как и при добавлении данного сокета в данную группу. Несмотря на то, что структура ip_mreq
относится к WinSock 1, в модуле WinSock ее описание отсутствует. Константы IP_ADD_MEMBERSHIP
и IP_DROP_MEMBERSHIP
в этом модуле объявлены, но работать с ними следует с осторожностью, потому что они должны иметь разные значения в WinSock 1 и WinSock 2. В WinSock 1 они должны иметь значения 5 и 6 соответственно, а в WinSock 2 — 12 и 13. Из-за этого нужно внимательно следить, чтобы значения соответствовали той библиотеке, из которой импортируется функция setsockopt: 5 и 6 — для WSock32.dll и 12 и 13 — для WS2_32.dll.
В WinSock 2 для присоединения сокета к группе объявлена функция WSAJoinLeaf
, прототип которой приведен в листинге 2.80.
Листинг 2.80. Функция WSAJoinLeaf
// ***** описание на C++ *****
SOCKET WSAJoinLeaf(SOCKET s, const struct sockaddr FAR *name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS, DWORD dwFlags);
// ***** описание на Delphi *****
function WSAJoinLeaf(S: TSocket; var Name: TSockAddr; NameLen: Integer; lpCallerData, lpCalleeData: PWSABuf; lpSQOS, lpGQOS: PQOS; dwFlags: DWORD): TSocket;
Параметры lpCallerData
и lpCalleeData
задают буферы, в которые помещаются данные, передаваемые и получаемые при присоединении к группе. Протокол IP не поддерживает передачу таких данных, поэтому при его использовании эти параметры должны быть равны nil
. Параметры lpSQOS
и lpGQOS
относятся к качеству обслуживания, которое мы здесь не рассматриваем, поэтому их мы тоже полагаем равными nil
.
Параметр S
определяет сокет, который присоединяется к группе, Name
— адрес группы, NameLen
— размер буфера с адресом. Параметр dfFlags
определяет, будет ли сокет служить для отправки данных ( JL_SENDER_ONLY
, 1), для получения данных ( JL_RECEIVER_ONLY
, 2) или и для отправки, и для получения ( JL_BOTH
, 4).
Функция возвращает сокет, который создан для взаимодействия с группой. В протоколах типа ATM подключение к группе похоже на установление связи в TCP, и функция WSAJoinLeaf
, подобно функции accept
, создаёт новый сокет, подключенный к группе. В случае UDP новый сокет не создается, и функция WSAJoinLeaf
возвращает значение переданного ей параметра S
.
Номер порта в параметре Name
игнорируется. Для получения групповых сообщений используется тот интерфейс, который система назначает для этого по умолчанию.
Чтобы прекратить членство сокета в группе, в которую он был добавлен с помощью WSAJoinLeaf
, нужно закрыть его посредством функции closesocket
. Если сокет, для которого вызывается функция WSAJoinLeaf
, находится в асинхронном режиме, то при успешном присоединении сокета к группе возникнет событие FD_CONNECT
(в [3] написано, что в одноранговых плоскостях управления FD_CONNECT
не возникает — это не соответствует действительности). Но в случае ненадежного протокола UDP возникновение этого события говорит лишь о том, что было отправлено IGMP-сообщение, извещающее о включении сокета в группу (это сообщение должны получить все маршрутизаторы сети, чтобы потом правильно передавать групповые сообщения в другие подсети). Однако FD_CONNECT
не гарантирует, что это сообщение успешно принято всеми маршрутизаторами.
Читать дальше
Конец ознакомительного отрывка
Купить книгу