Чтение онлайн

на главную

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

Затем выполняется собственно добавление сокета в группу. В WinSock 12 для этого потребуется функция

setsockopt
с параметром
IP_ADD_MEMBERSHIP
, в качестве уровня следует указать
IPPROTO_IP
. При этом через параметр
optval
передается указатель на запись
ip_mreq
, описанную так, как показано в листинге 2.79.

Листинг 2.79. Тип
TIPMreq

// ***** Описание на C++ *****

struct ip_mreq {

 struct in_addr imr_multiaddr;

 struct in_addr imr_interface;

}

// *****
Описание на Delphi *****

TIPMreq = packed record

 IMR_MultiAddr: TSockAddr;

 IMR_Interface: TSockAddr

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
не гарантирует, что это сообщение успешно принято всеми маршрутизаторами.

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
позволяет программе изменить это значение.

Поделиться:
Популярные книги

Идущий в тени 4

Амврелий Марк
4. Идущий в тени
Фантастика:
боевая фантастика
6.58
рейтинг книги
Идущий в тени 4

Дракон с подарком

Суббота Светлана
3. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
6.62
рейтинг книги
Дракон с подарком

Я снова не князь! Книга XVII

Дрейк Сириус
17. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я снова не князь! Книга XVII

Метка драконов. Княжеский отбор

Максименко Анастасия
Фантастика:
фэнтези
5.50
рейтинг книги
Метка драконов. Княжеский отбор

Авиатор: назад в СССР 11

Дорин Михаил
11. Покоряя небо
Фантастика:
альтернативная история
5.00
рейтинг книги
Авиатор: назад в СССР 11

На границе империй. Том 7. Часть 5

INDIGO
11. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 7. Часть 5

Темный охотник 6

Розальев Андрей
6. КО: Темный охотник
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Темный охотник 6

Корпулентные достоинства, или Знатный переполох. Дилогия

Цвик Катерина Александровна
Фантастика:
юмористическая фантастика
7.53
рейтинг книги
Корпулентные достоинства, или Знатный переполох. Дилогия

Все еще не Герой!. Том 2

Довыдовский Кирилл Сергеевич
2. Путешествие Героя
Фантастика:
боевая фантастика
юмористическое фэнтези
городское фэнтези
рпг
5.00
рейтинг книги
Все еще не Герой!. Том 2

Довлатов. Сонный лекарь 3

Голд Джон
3. Не вывожу
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Довлатов. Сонный лекарь 3

Попаданка в деле, или Ваш любимый доктор - 2

Марей Соня
2. Попаданка в деле, или Ваш любимый доктор
Любовные романы:
любовно-фантастические романы
7.43
рейтинг книги
Попаданка в деле, или Ваш любимый доктор - 2

Возмездие

Злобин Михаил
4. О чем молчат могилы
Фантастика:
фэнтези
7.47
рейтинг книги
Возмездие

Ваше Сиятельство 8

Моури Эрли
8. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Ваше Сиятельство 8

Чемпион

Демиров Леонид
3. Мания крафта
Фантастика:
фэнтези
рпг
5.38
рейтинг книги
Чемпион