Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование в сетях Windows

.pdf
Скачиваний:
538
Добавлен:
11.03.2015
Размер:
3.02 Mб
Скачать

318

ЧАСТЬ II Интерфейс прикладного программирования Winsock

 

Листинг 11-1. (продолжение)

* д

j^p"

 

ц

 

 

i

.<* i*rto)

//Описание:

//Вывод информации об использовании и выход

void usage(char *progname)

printf("usage:

%s -s -nrstr -p.int -i:str -1 -n:int\n",

progname);

 

 

 

 

printf(" -s

Act as server (send data);

otherwise\n");

printf("

receive data.\n");

 

 

 

printf(" -m:str Dotted decimal multicast IP addres to join\n");

pnntf("

The default group is.

Xs\n",

MCASTADDR);

printf(" -p:int Port number to use\n"),

 

 

 

printf("

The default port is:

Xd\n",

MCASTPORT);

printf(" -i:str Local interface to bind to;

by default \n");

p n n t f C

use INADDRY_ANY\n");

 

 

 

pnntf(" -1

Disable loopback\n");

 

 

 

printf(" -n:int Number of messages to send/receive\n");

ExitProcess(-i);

 

 

 

// Функция: ValidateArgs

 

 

 

// Описание:

 

 

 

»«e->>

//Анализ параметров командной строки и установка некоторых глобальных

//флагов в зависимости от значений

void ValidateArgs(int argc, char **argv)

int

i;

 

 

 

dwlnterface = INADDR_ANY;

 

®

[*m

dwMulticastGroup = inet_addr(MCASTADDR);

2

 

>№'1

lPort

= MCASTPORT;

 

f

в

dwCount = DEFAULT_COUNT;

 

3

'e b 4

for(i = 1; l < argc; i++)

 

_

 

if ((argv[i][0] == '-•) || (argv[i][O] == V ) )

 

 

 

 

switch (tolower(argv[i][1]))

 

•*'

 

case

's'

// Отправитель

 

bSender = TRUE;

 

break;

 

case

'm'.

// Многоадресная группа

 

if (strlen(argv[i]) > 3)

dwMulticastGroup = inet_addr(&argv[i][3]);

J

• и«« с -«Mi ГЛАВА 11 Многоадресная рассылка 319

Листинг 11-1. (продолжение)

 

 

 

 

 

 

 

break;

 

 

 

 

 

 

 

Ohi

 

case

' i ' :

//

Локальный

интерфейс

 

 

 

 

 

if (strlen(argv[i])

>

3)

4т;

тш юяе-н \\

 

 

dwlnterface = inet_addr(&argv[i][3]);

 

\\

 

>

break;

 

 

 

 

 

,v*lP<<

.,< *)«9iA°>tt>b.L,U.i

 

case

' p ' :

//

Номер порта

 

 

 

 

'/

if ( s t r l e n ( a r g v [ i ] ) > 3)

 

 

 

 

pt

lPort

=

atoi(&argv[i][3]);

 

 

 

 

<^

break;

 

 

 

 

 

 

 

 

 

case

' 1 ' :

//

Запретить

образование петли?

<r>i*tn

 

i

bLoopBack

= TRUE;

 

 

 

 

 

 

ЖИ

break;

 

 

 

 

 

 

et«*09

вшвдеоЗ \\

 

case

' n ' :

//

 

Количество

сообщений

для отгцмМИЦ/^рЯМЯГтя^ \\

 

 

dwCount

= a t o i ( & a r g v [ i ] [ 3 ] ) ;

 

 

\\

 

 

break;

 

 

 

 

 

/Jwtaee « Шоса)) U

 

default:

 

 

 

 

 

 

 

>

 

 

usage(argv[O]);

4

,'n/ii

 

 

 

 

 

break;

 

 

 

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

x

 

 

 

 

 

 

 

 

 

 

 

return;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

л

 

//

 

 

 

 

 

 

 

 

ЛЬ

i.leool

// Функция: main

 

 

 

 

 

 

 

 

 

//

 

 

 

 

 

 

 

 

 

nit!) П

// Описание:

 

 

 

 

 

 

 

 

it®

//

Анализ параметров командной строки,

загрузка

библиотеки

Wmsock

}

//создание сокета и присоединение к многоадресной группе. Если програци*

//

запущена как отправитель,

то начинается отправка сообщений

sit.

 

//

группе,

иначе вызывается

recvfrom() для

 

•*)

//

чтения

сообщений, отправленных группе.

,Л91

\

//

 

 

 

 

{

im: main(int argc, char **argv)

 

 

 

{

 

ш т щ

язд «»••.#»•

чч*щг

вав

WSADATA

 

wsd;

в&В«фчвгнк

<

Тыннв,поащпmrox Л

struct

sockaddr_in

local,

 

 

W

 

 

remote,

 

JW

-.введет

 

 

from;

 

 

 

struct

ipjnreq

mcast;

 

 

 

SOCKET

 

sockM;

 

 

 

TCHAR

 

recvbuf[BUFSIZE],

 

 

 

 

 

sendbuf[BUFSIZE];

 

 

 

int

 

len = sizeof(struct sockaddr_in),

 

 

 

 

optval,

 

 

 

 

 

ret;

 

 

 

см.след.апр.

320

ЧАСТЬ II Интерфейс прикладного программирования Winsock

Листинг 11-1. (продолжение)

DWORD i=0;

// Анализ командной строки и загрузка Winsock

ValidateArgs(argc, argv);

if (WSAStartup(MAKEW0RD(1, 1), &wsd) != 0)

printf("WSAStartup failed\n"); return - 1 ;

//

Создание сокета. В

Winsock 1 вам

не потребуется никаких специальных

//

флагов для указания

многоадресной

рассылки

if ((sockM = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID.SOCKET)

printf("socket failed with: Xd\n", WSAGetLastErrorO); WSACleanupO;

return - 1 ;

// Привязка сокета к локальному интерфейсу.

Это нужно для приема данных

{

 

 

local.sin_family = AF_INET;

 

 

 

 

 

local.sin_port

= htons(iPort);

 

 

 

 

local.sin_addr.s_addr = dwlnterface;

 

 

 

 

if

(bind(sockM,

(struct

sockaddr *)&local,

 

 

 

\\

 

sizeof(local)) == SOCKET.ERROR)

 

 

«wnO

v.

{

 

 

 

 

'

 

,tk

\\

 

printffbind

failed with: Xd\n", WSAGetLastErrorO);

V

 

 

closesocket(sockM);

 

 

 

 

ct

 

WSACleanupO;

 

 

 

 

 

 

 

return-1;

 

 

 

, ,„41

•(*

 

 

 

 

 

 

In.1

 

 

//

Настройка структуры

im_req для указания

группы, к которой мы

 

 

}

// хотим присоединиться,

и интерфейса

<

 

ATAQAS

//

 

 

 

 

u

Mj\ttomk9Q&

 

remote.sin_family

=

AF_INET;

 

 

 

 

remote.sin_port

 

=

htons(iPort);

 

 

 

 

remote.sin_addr.s_addr =

dwMulticastGroup;

f№%ajql

Л*,

 

 

 

 

 

 

 

T?

 

 

 

mcast.imr_multiaddr.s_addr = dwMulticastGroup;

I

 

 

mcast.imr_interface.s_addr

= dwlnterface;

 

 

 

 

if (setsockopt(sockM, IPPR0TO_IP, IP_ADD_MEMBERSHIP, (char *)&mcast, sizeof(mcast)) == SOCKET.ERROR)

printf("setsockopt(IP_ADD_MEMBERSHIP) failed: Xd\n",

Г Л А В А

11 Многоадресная рассылка

321

Чистинг11-1. (продолжение')

 

 

 

WSAGetLastErrorO);

 

 

 

closesocket(sockM);

 

 

 

WSACleanupO;

 

 

 

return -1;

 

 

 

// Настройка значения TTL (по умолчанию - 1)

 

 

optval = 8;

 

 

 

if (setsockopt(sockM, IPPR0TO_IP, IP_MULTICAST_TTL,

 

 

(char O&optval, sizeof(int)) == SOCKET.ERROR)

 

 

printf("setsockopt(IP_MULTICAST_TTL)

failed: Xd\n",

10* »

...•

WSAGetLastErrorO);

 

 

 

closesocket(sockM);

 

 

 

WSACleanupO;

return -1;

//Запрет петли, если это было выбрано. Заметьте,

//что в Windows NT 4 и Windows 95 петлю запретить нельзя

if

(bLoopBack)

 

 

 

optval = 0;

 

 

 

if (setsockopt(sockM, IPPR0T0_IP, IP_MULTICAST_LOOP,

 

 

(char *)&optval, sizeof(optval)) == S0CKET_ERROR)

," I

 

printf("setsockopt(IP_MULTICAST_LOOP) failed: Xd\n",

m

 

 

WSAGetLastErrorO);

i/

 

closesocket(sockM);

14

 

WSACleanupO;

 

 

return-1;

 

 

 

>

 

 

 

if

(IbSender)

// Клиент

 

 

// Прием

порции

данных

 

 

f o r ( i =

0; i <

dwCount;

 

if ((ret =

recvfrom(sockM,

recvbuf, BUFSIZE, 0,

(struct

sockaddr

*)&from, &len)) == SOCKET_ERR0R)

{

 

 

 

printf("recvfrom

failed

with: Xd\n",

WSAGetLastErrorO);

closesocket(sockM);

WSACleanupO;

см.след.стр.

322 ЧАСТЬ II Интерфейс прикладного программирования Winsock

Листинг 11-1.

 

(продолжение)

 

 

 

 

 

 

 

 

 

 

 

 

 

return - 1 ;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

и в ) :

 

 

r e c v b u f [ r e t ]

= 0 ;

 

 

 

 

 

g ^

 

 

 

'<(>

 

 

-•*'

printf("RECV:

- Xs'

from

<Xs>\n",

recvbuf,

 

 

 

 

 

 

i

 

i n e t _ n t o a ( f r o m . s i n _ a d d r ) ) ;

 

 

 

 

 

 

 

 

 

{

 

 

 

 

 

 

 

 

 

 

та) JTT RH««»*ine

к

 

itH \\

}

 

 

 

 

 

 

 

}

 

 

 

 

 

 

 

 

else

 

 

// Сервер

 

 

 

 

 

 

 

 

 

;в.

// Отправка

порции данных

 

 

 

 

 

 

 

 

 

 

 

< V14}O<&(« isda)

//

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

J

f o r ( i =

0;

i < dwCount;

i++)

 

 

 

 

 

 

 

 

 

 

ц

sprintf(sendbuf,

"server 1: This

is a test: Xd",

i ) ;

 

 

 

J

if (sendto(sockM,

(char

*)sendbuf,

strlen(sendbuf),

0,

 

 

M

 

(struct

sockaddr

*)&remote,

 

 

 

 

 

 

 

;f-

niuJei

 

sizeof(remote))

==

SOCKET_ERROR)

rV., t,

,

;;

 

 

 

 

{

{

 

 

 

 

 

 

 

 

 

IW»CI

oit

« u i

.wvren

тщпв£ \S

 

printf("sendto failed with: Xd\n"ipbncW # f> ГО вноЬоШ a OTS< \\

 

 

WSAGetLastErrorO);

 

 

 

 

 

 

 

 

 

 

\\

 

closesocket(sockM);

t (

**.»<*}

>

wysw» аяя «р»#Й1#%*ВД4Лк) *'t

 

WSACleanupO;

 

 

 

 

 

 

 

 

 

 

 

 

 

}

 

return - 1 ;

 

 

 

 

 

 

 

 

 

 

;0

»

lev.t^e

}

 

 

 

 

 

>(

' ч"

ОТО""""

'

'

f qo^sf

 

*fc) Iri

Sleep(500);

 

 

 

 

 

'ta}i

 

 

 

>Я(«

 

 

 

}

 

 

 

 

 

 

 

 

JW

 

 

 

^*)^

 

 

 

// Выход из

группы

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

if (setsockopt(sockM, IPPR0T0_IP, IP_DROP_MEMBERSHIP,

 

 

 

 

 

 

(char *)&mcast, sizeof(mcast)) == S0CKET_ERR0R)

 

 

 

 

 

 

 

<

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4

printf("setsockopt(IP_DROP_MEMBERSHIP) failed: Xd\n",

 

 

 

 

<

WSAGetLastErrorO);

 

 

 

 

 

 

 

 

 

 

 

 

 

closesocket(sockM);

 

 

 

 

it),

 

 

 

 

 

 

&

^

}

WSACleanupO;

 

 

 

 

 

'

 

 

 

 

 

 

 

 

 

\\

return 0;

 

 

 

 

 

 

 

 

 

 

 

 

*b

>

i

;0

 

Одно предостережение при организации рассылки в Winsock 1: используйте корректные заголовочный файл и библиотеки для компоновки. Если вы загружаете библиотеку Winsock 1.1, подключите Winsock.h и компонуйте его с Wsock32.1ib. Для версии 2 или выше подключайте Winsock2.h и Ws2tcpip.h и компонуйте их с Ws2_32.1ib. Это необходимо, поскольку существует два множества значений для констант IP'_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IPJWULTICASTJF и IP ^MULTICAST LOOP. Исходная спецификация значений, написанная Стивеном Дирингом (Stephen Deering), никогда офи-

" ' " Г Л А В А 11 Многоадресная рассылка

323

'циально не включалась в спецификацию Winsock. В результате они изменились в спецификации Winsock 2. Конечно, если вы используете раннюю вер- С(ию Winsock, компоновка с wsock32.lib решит все проблемы и константы получат корректные значения даже при запуске на компьютере с Winsock 2.

РассылкасредствамиWinsock2

Многоадресная рассылка в Winsock 2 немного сложнее, чем в Winsock 1, но поддерживает разные протоколы, что дает дополнительные возможности, например, использовать Quality of Service (QoS). Кроме того, рассылка в Winsock 2 позволяет применять протоколы, поддерживающие маршрутизируемые схемы. Параметры сокета больше не нужны для инициализации членства в группе — им на смену пришла функция WSAJoinLeaf.

SOCKET WSAJoinLeaf( SOCKET s,

const struct sockaddr FAR * name, int namelen,

LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS,

LPQOS lpGQOS, DWORD dwFlags

);

Параметр 5 — описатель сокета, возвращенный WSASocket. Переданный сокет должен быть создан с соответствующими флагами, иначе WSAJoinLeaf вернет ошибку WSAEINVAL. Помните о необходимости задать два флага: один показывает, будет ли этот сокет маршрутизируемым в плоскости управления, другой — будет ли сокет маршрутизируемым в плоскости данных. Флаги для плоскости управления — WSA_FIAG_MULTIPOINT_C_ROOT и WSA_FLAG_MULTIPOINT_C_LEAF. Флаги для плоскости данных - WSA_FLAG_MULTIPOINT_

D_ROOTKWSA_FLAG_MULTIPOINT_D_LEAF.

Второй параметр — структура SOCKADDR, специфичная для используемого протокола. Для маршрутизируемых схем управления (например, ATM) этот адрес указывает клиента, которого нужно пригласить, а для немаршрутизируемых схем (например, IP) — это адрес группы, к которой узел присоединяется.

Параметр namelen — длина в байтах параметра пате. Параметр lpCallerData используется для передачи буфера данных партнеру в установленном сеансе, a lpCalleeData указывает буфер, который будет передан обратно. Эти два параметра пока не реализованы на платформах Windows и должны быть равны NULL. Параметр lpSQOS задает структуру FLОWSPEC, указывающую требуемую пропускную способность для приложения (подробнее о QoS — в главе 12.) Параметр lpGQOS игнорируется, поскольку ни одна из платформ Windows не поддерживает группы сокетов. Последний параметр — dwFlags, показывает роль узла: отправка данных, прием данных, или и то, и другое. Возможные значения —JL_SENDER_ONLYJL_RECEIVER_ONLYviJL_BOTH.

324

ЧАСТЬ II Интерфейс прикладного программирования Winsock

I

 

 

7

Функция возвращает описатель SOCKET для сокета, связанного с многот адресной группой. Если вызов WSAJoinLeafвыполнен с асинхронным (неблокирующим) сокетом, возвращаемый описатель сокета не пригоден к использованию, пока не завершится операция присоединения. Например, в этом случае после вызова WSAAsyncSelect или WSAEventSelect описатель не будет действителен, пока исходный сокет 5 не вернет сообщение FD_CONNECT. Сообщение FD_CONNECT генерируется только в маршрутизируемой схеме управления, в которой параметр пате задает конкретный адрес конечной точки.

В табл. 11-1 перечислены обстоятельства, при которых приложение получает сообщение FD_CONNECT. Вы вправе аннулировать ожидающий выполнения запрос на присоединение для этих неблокирующих режимов, вызвав closesocket на исходном сокете. Корневой узел в многоточечном сеансе может вызывать WSAJoinLeaf один или несколько раз, чтобы добавить несколько листовых узлов; впрочем, в каждый момент времени ожидать выполнения может только один запрос на многоточечное соединение.

Табл.11-1.ДействияWSAJoinLeaf

Плоскость s

Имя

Действие

Прием

Возвращение

 

 

управления

 

 

уведомления

описателя

 

 

 

 

 

FDCONNECT сокета

 

 

Маршрутиc_root Адрес Корень

Да

Используется для

зируемая

листа

приглашает

 

уведомленияFDCLOSE

 

 

лист

 

и для отправки данных

 

 

Листини-

 

только этому листу

cjeaf

Адрес

Да

Дубликат*

.тэнсп-

 

корня

циирует

 

 

 

 

 

 

соединение

 

 

'ыесж..-

 

 

с корнем

 

 

 

 

Немаршруc_root —

Невозможная

_

оэроп:

тизируемая

 

комбинация

 

 

А1ОЧ\ТV

cjeaf

Адрес

Лист присое-

Нет

Дубликат 5

>ОШ <\

группы диняется к группе

Как мы уже упоминали, запрос на присоединение для неблокирующих сокетов не может завершиться немедленно. Если сокет переведен в неблокирующий режим посредством ioctlsocket и команды FIONBIO, вызов WSAJoinLeafне вернет ошибку WSAEWOULDBLOCK, поскольку эта функция фактически выдаст сообщение об успешном запуске Заметьте, что в асинхронной модели ввода-вывода единственный способ узнать об успешном запуске — сообщение FD_CONNECT. (Подробнее об асинхронных моделях WSAAsyncSelect и WSAEventSelect — в главе 8.) Блокирующие сокеты не могут уведомить приложение об удачном или ошибочном завершении WSAJoinLeaf. Другими словами, применять неблокирующие сокеты не стоит, поскольку нет однозначного способа определить успешно ли присоединение к группе, пока сокет не будет задействован в последующих вызовах Winsock (которые вернут ошибку, если присоединения не произошло).

Г Л А В А 11 Многоадресная рассылка

325

Описатель сокета, возвращенный WSAJoinLeaf, зависит от того, является ли сокет маршрутизируемым или листовым узлом. Для маршрутизируемого узла параметр пате указывает адрес конкретного листа, который приглашается в многоточечный сеанс. Чтобы c_root поддерживал членство листьев, WSAJoinLeaf возвращает для листа новый описатель сокета.

Новый сокет имеет те же свойства, что и корневой описатель, использованный для приглашения, включая любые асинхронные события, зарегистрированные по асинхронным моделям ввода-вывода типа WSAEventSelect и WSAAsyncSelect. Впрочем, эти новые сокеты следует применять только для получения уведомления FD_CLOSE от листа. Любые данные, которые нужно отправить многоадресным группам, должны отправляться через сокет cjroot. Иногда вы можете отправить данные на сокет, возвращенный WSAJoinLeaf, но их получит только лист, соответствующий этому сокету (это позволяет протокол ATM). Наконец, чтобы удалить листовой узел из многоточечного сеанса, корень просто вызывает closesocket на сокете, соответствующем этому листу.

С другой стороны, когда WSAJoinLeafвызывается с листовым узлом, параметр пате задает адрес либо корневого узла, либо многоадресной группы. В первом случае присоединение инициируется листом, что в настоящее время не поддерживает ни один протокол (спецификация ATM UNI 4.0 будет делать это). Второй пример — рассылка в IP. В любом случае описатель сокета, возвращенный WSAJoinLeaf — это тот же описатель сокета, что был передан в 5. Когда вызов WSAJoinLeaf служит для присоединения со стороны листа, корневой узел слушает входящие соединения, используя методы bind, listen и accept/WSAAccept, как обычно на сервере. Когда приложение хочет удалить себя из многоадресного сеанса, вызывается closesocket на том сокете, который прекращает членство (при этом также освобождаются ресурсы сокета). Табл. 11-1 резюмирует действия, выполняемые в зависимости от типа плоскости управления, и параметры, которые передаются на сокет. С ее помощью также можно определить, возвращается ли новый описатель сокета после удачного вызова функции и получает ли приложение уведомление FD_CONNECT.

Допустим, приложение вызывает accept или WSAAccept, чтобы ожидать приглашения от корня, либо выполняет роль корня, чтобы ожидать запросы на присоединение от листьев. Тогда функция возвращает сокет, который является описателем сокета c_leaf (такой же возвращает WSAJoinLeaf). Для работы с протоколами, которые поддерживают соединения, инициированные как корнем, так и листом, в качестве входного параметра для WSAJoinLeaf Допустимо передавать слушающий сокет c_root.

После вызова WSAJoinLeaf возвращается новый описатель сокета. Этот описатель не применяется для отправки и приема данных: он просто показывает, что приложение — член многоадресной группы. Для операций отправки и приема используется исходный описатель сокета, полученный от

WSASocket и затем переданный в WSAJoinLeaf. Вызов closesocket для нового описателя прекратит членство приложения в группе. В результате вызова closesocket на сокете c_root все связанные с ним узлы c_leaf, использующие асинхронную модель ввода-вывода, получат уведомление FD CLOSE.

326

ЧАСТЬ II Интерфейс прикладного программирования Winsock

Примермногоадреснойрассылки вIP-сетисредствамиWinsock2

Листинг 11-2 содержит программу Mcastws2.c, которая иллюстрирует присоединение и выход из многоадресной группы с помощью WSAJoinLeaf. Это измененный пример организации IP-рассылки средствами Winsock 1. Отличие в том, что вызовы присоединения (выхода) здесь переписаны под WSAJoinLeaf.

Листинг 11-2. Пример организации многоадресной рассылки средствами Winsock 2

// Модуль: Mcastws2.c

 

//

 

 

«include

<winsock2.h>

 

«include

<ws2tcpip.h>

 

«include

<stdio.h>

 

«include

<stdlib.h>

 

«define

MCASTADDR

"234.5.6.7"

«define

MCASTPORT

25000

«define

BUFSIZE

1024

«define

DEFAULT_COUNT

500

BOOL

bSender

= FALSE,

// Действовать как отправитель?

 

 

bLoopBack = FALSE;

// Запретить

образование петли?

 

DWORD

dwlnterface,

// Локальный интерфейс для привязки

 

 

dwMulticastGroup,

// Многоадресная

группа, к которой присоединиться

 

dwCount;

 

// Количество

сообщений

для отправки/приема

short

iPort;

 

// Номер

используемого

порта

^

 

 

 

 

 

 

 

 

JK'I

Н Оз

II

 

 

 

 

 

 

 

Я''

.ИНТ

// Функция: usage

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

( С 1 " • ">

I/ Описание:

 

 

 

 

 

 

 

 

//

Вывод информации об

использовании

и

выход

 

 

 

//

 

 

 

 

 

 

 

 

 

void

usage(char •progname)

 

 

 

 

 

 

 

{

 

 

 

 

 

 

 

 

 

printf("usage: Xs -s -m:str -p:int -i:str -1 -n:int\n",

 

 

progname);

 

 

 

 

 

 

 

printfC

-s

Act as server

(send data); otherwise\n");

 

printfC

 

receive data.\n");

 

 

 

printfC

-m:str

Dotted decimal

multicast

IP addres "

 

 

"to Join\n");

 

 

 

 

 

 

 

printfC

 

The default

group is:

Xs\n",

MCASTADDR);

 

printfC

-p:lnt

Port number to

use\n");

 

 

 

printfC

 

The default

port

is:

Xd\ri",

MCASTPORT);

 

printf("

-i:str

Local interface to bind to; by default \n");

 

т

 

 

 

Г Л А ВА 11 Многоадресная рассылка

327

Листинг 11 -2.

(продолжение)

 

 

printfC

 

use INADDRY_ANY\n");

 

 

 

printf("

-1

Disable loopback\n");

 

 

 

printfC

-n:int

Number of messages to send/receive\n"); »b

 

 

 

ExitProcess(-i);

»j1

 

 

II

 

 

. j » c y .

 

 

И

Функция: ValidateArgs

 

 

 

 

// Описание:

ь

//

Анализ параметров командной строки

и у о п м м к * некоторых глобальных

//флагов в зависимости от значений

//

 

 

1,

 

void ValidateArgs(int argc,

char

**argv)

 

 

dwlnterface = INADDR_ANY;

 

IHBH ОТ ,апвт»в»|»птс

 

dwMulticastGroup = inet_addr(MCASTADDR);(oitv>ei

 

iPort = MCASTPORT;

 

 

Яньс

 

dwCount = DEFAULT_COUNT;

 

 

 

 

for(i=1; i < argc ;:

 

 

 

 

{

 

 

 

ATA0A3W

if ((argv[i][O] == '-') || (argv[i][O]

 

{

 

at-

 

 

switch (tolower(argv[i][i]))

 

ТЗЖЮ8

{

 

 

 

 

 

 

ЙАНЗТ

case ' s ' :

//Отправитель

«Те-

 

bSender = TRUE; break;

n

\\

\\

\\

\\

\\

\\

tnl

case

'пГ:

// Многоадресная группа

 

 

if (strlen(argv[i]) > 3)

 

 

dwMulticastGroup = inet_addr(4argv[i][3]);

 

break;

 

емпан

case

'i':

// Локальный интерфейс

\\

 

if (strlen(argv[i]) > 3)

*<-*blfaV

 

dwlnterface = met_addr(4argv[i][3]);

 

break;

 

 

case

'p':

// Номер порта

 

 

if (strlen(argv[i]) > 3)

1

 

iPort = atoi(&argv[i][3]);

-I

 

break;

 

 

case

'1':

// Запретить образование петли?

 

bLoopBack = TRUE;

 

 

break;

 

 

case

'n':

// Количество сообщений для

отправки/приема

см.след.стр.