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

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

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

378

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

 

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

1MNT»NR

serverQos.ReceivingFlowspec = flowspec_g711;

 

serverQos.ProviderSpecific.buf = NULL;

 

serverQos.ProviderSpecific.len = 0;

 

if

(bConfirmResv)

 

 

SetQosReserveInfo(&serverQos);

 

// Функция: usage

i*e-

//

 

//Описание:

//Печать информации об использовании

void usage(char

progname)

 

{

Xs-q:x -s -c:IP\n", progname);

printf("usage

printf("

-q:[b,d,a,e] When to request QOS\n");

printf("

b

Set QOS before bind or connect\n");

printf("

d

Set QOS during accept condfunc\n");

printf("

a

Set QOS after sessionsetup\n");

printf("

e

Set QOS only upon receipt ofFD_QOS\n");

printf("

-s

Act asserver\n");

printf("

-c:Server-IP Act asclient\n");

printf("

-w

Wait to send until RESV hasarrived\n");

printf("

-r

Confirm reservationrequest\n");

ExitProcess(-i);

>

W

\\

W

\\

A

V.

°op op(;ор

oo o*

op

=cp

.qi

//Функция: ValidateArgs

//Описание:

//

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

и задает глобальные

переменны*,

 

//

чтобы определить,

как должно работать

приложение

 

\\

 

 

 

 

 

 

 

 

 

 

\\

void ValidateArgs(int

argc,

char

**argv)

 

 

\\

 

 

 

 

 

 

 

 

 

 

\\

int

i;

 

 

 

 

 

 

 

\\

 

 

 

 

 

 

 

 

 

ив м&отр

\\

//

Инициализация

глобальных

переменных значениями по умолчанию

^ " w o н

\\

 

 

 

 

 

 

 

 

 

 

\\

iSetQos = SET_QOS_NONE;

 

 

 

 

•ov

bServer = TRUE;

 

 

 

 

 

 

 

bWaitToSend =

FALSE;

 

 

 

VarnZв

 

bConfirmResv =

FALSE;

 

 

 

 

 

for(i = 1; i < argc;

 

 

 

 

 

 

{

 

 

 

 

 

 

(argv[i][0]

 

 

 

if

((argv[i][0]

==

'-'

 

 

/"ЛАВА 12

Качцрриойаяршвания

379

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

К Rtt(vOK\rO

 

 

switch

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

 

case ' q ' :

// Когда включать QOS

 

 

if (tolower(argv[i][3]) == ' b ' )

objcoum

iSetQos = SET_QOS_BEFORE;

o b j v a - -

else if (tolower(argv[i][3]) == 'd ' )

 

 

iSetQos = SET_QOS_DURING;

if

{oi*;*

else if (tolower(argv[i][3]) == 'a ' )

 

Wof

iSetQos = SET_QOS_AFTER;

 

 

else if

(tolower(argv[i][3]) == 'a 1 )

П

Q,

iSetQos = SET_QOS_EVENT;

ureaa

 

;te-<

j i i j .

• «boOwb

C30WQ

iA -

 

,«.. fsVwb

 

;*t>TY8wb

 

>tJaoH3W = J e i

 

else

 

 

 

 

(№'-.

 

j)1 >03 sss J

 

 

 

usage(argv[O]);

 

 

 

 

 

j

 

 

break;

 

 

 

 

di

 

 

 

 

 

 

 

 

 

 

t*1 (

 

 

 

*« '

case ' s ' :

// Сервер

 

 

 

Ч'-,АЧ nni 1 a t

 

 

printf("Server

flag

set!\n");

 

 

 

<

 

bServer

= TRUE;

 

 

 

 

JOS'! тлит

 

break;

 

 

 

 

 

 

 

{

 

case ' c ' :

// Клиент

 

 

 

 

 

 

 

 

 

 

 

 

printf("Client

flag

set!\n");

 

 

 

S\

 

 

bServer

= FALSE;

 

 

 

 

 

 

 

 

 

 

 

4rtO

 

 

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

 

 

 

 

\\

 

 

strcpy(szServerAddr, &argv[i][3]);

 

 

 

 

 

ынт итО \\

 

else

 

 

 

w?>

 

 

aoqH

\\

 

 

usage(argv[O]);

 

»nfl

 

p.

1 ЙОГявим

\\

 

break;

 

 

 

 

 

 

 

\\

 

case

'w':

//

He отправят» до?

 

 

 

 

4 o O " i Ъ»(*3 -1R0W

f

 

 

II

пока

не поступилосообщение

RESV

^ j

 

 

bWaitToSend =

TRUE;

 

\1.'Ш

-

 

O i l '

 

 

 

break;

 

 

 

;jjtJM

 

BJtt

'f

 

case

' r':

 

 

 

j '{№

«

 

 

 

 

 

bConfirmResv = TRUE;

 

.38JA4

 

jooe

 

 

break;

 

 

 

,Ct »

J

'0

ftfiOWl

 

default:

 

 

 

 

 

 

 

 

 

 

usage(argv[O]);

( 0

* • « i . ^ i

 

Si)

t :

 

 

break;

 

,.*.* m4m],

« v » 4 t * [ l

 

 

 

}

ibrit«to

return;

)3,

// Функция: AbleToSend

f)

//Описание:

//Проверяет, могут ли данные быть отправлены на сокете до поступления

си.след.стр.

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

Листинг 12-1.

 

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

 

 

 

 

И

сообщений

RESV.

Эта функция проверяет,

достаточен ли

имеющийся в

настоящий

//

момент

в сети

негарантированный уровень

для уровней

00S, заданных

на сокете.

//

 

 

 

 

 

 

 

 

BOOL

AbleToSend(SOCKET s)

 

 

 

')' #еео

{

 

 

 

 

 

 

" •

 

 

int ret;

 

 

 

 

 

 

DWORD

dwCode = ALLOWED_TO_SEND_DATA,

 

Jla.

 

 

dwValue,

 

 

 

 

 

 

dwBytes;

 

 

 

 

 

ret = WSAIoctl(s, SIO_CHK_QOS, idwCode,

sizeof(dwCode),

 

 

 

 

&dwValue, sizeof(dwValue), &dwBytes, NULL, NULL);

 

 

if (ret

==

SOCKET_ERR0R)

 

 

 

 

 

{

 

 

 

 

 

 

 

 

pnntf("WSAIoctl() failed: Xd\n",

WSAGetLastErrorO);

 

 

return

FALSE;

 

 

 

 

 

>

 

 

 

 

 

 

 

 

return

(BOOL)dwValue;

 

 

 

 

//Функция: ChkForQosStatus

//Описание'

//Проверяет наличие объекта RSVP_STATUS_INFO и определяет,

//имеются ли в нем нужные флаги

//

 

 

 

 

 

 

 

DWORD ChkForQosStatus(QOS *lpqos, DWORD dwFlags)

 

o<>eo

 

{

 

 

 

 

 

 

 

QOS_OBJECT_HDR

*ob]hdr

=

NULL;

"НИ"

Ш

 

RSVP.STATUS INFO «status = NULL;

 

MI J

 

char"

"

.bufptr

=

NULL;

 

«* *S*8*" ЗД<№'

BOOL

 

bDone

=

FALSE;

 

3d

 

DWORD

 

obicount

= 0,

 

id

 

 

 

 

 

 

 

*Xuisfei>

 

if (lpqos->ProviderSpecific.len == 0)

 

su

 

return 0;

 

 

 

 

>id

 

 

 

 

 

 

 

 

{

bufptr = lpqos->ProviderSpecific.buf;

 

' '|(""в

{

objhdr

= (QOS_OBJECT_HDR

*)bufptr;

 

 

 

 

 

 

 

 

 

 

'91

 

 

 

 

 

 

 

{

while

(ibDone)

 

 

 

 

 

 

{

 

 

 

 

 

 

\\

if (objhdr->ObjectType == RSVP_OBJECT_STATUS_INFO)

<v« v\

{

status = (RSVP_STATUS_INFO *)objhdr;

 

 

 

 

 

 

 

 

if (status->StatusCode & dwFlags)

 

 

 

 

return 1;

 

 

 

 

 

 

* j f r 12

Качество обслЦувания

381

Листинг 12-1.

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

 

 

 

}

 

 

net.tudw

 

else if (objhdr->ObjectType == QOS_OBJECT_END_OF_LIST)

 

 

bDone = TRUE;

 

3ten)*•*

 

bufptr += objhdr->Objeel:Length;

 

en

 

objeount += objhdr->ObjectLength;

 

 

 

objhdr =

(Q0S_0BJECT_HDR *)bufptr;

 

u.

 

 

 

 

 

if (objeount >= lpqos->ProviderSpeclflc.l»n)

 

 

bDone = TRUE;

Art ,[> 2)V

 

 

return 0;

 

 

 

 

-*

A3W

1С)

 

//Функция. HandleClientEvents

//Описание'

//

Эта функция вызывается функцией Server для

обработки событий, fjnx 5

 

//

которые

произошли на описателях клиентов SOCKET. Массив

<

//

сокетов

передается вместе с массивом событий и индексом клиенте,i»»oM

\\

//

получившего оповещение. В функции событие

декодируется,

\\

//

и выполняется соответствующее действие.

 

Г вп)) 1

void HandleClientEvents(SOCKET socks[],

HANDLE events[],

int index) tn) IJt

 

WSANETWORKEVENTS

ne;

 

 

!)i

 

char

databuf[4096];

 

 

 

WSABUF

wbuf;

 

 

Л' . кЗТШ

iq

DWORD

dwBytesRecv,

 

 

 

 

 

dwFlags;

•>•

%"

- ' c "

~ INK)! \\

int

ret,

 

 

WK, \\

 

 

i;

 

 

Г\\

 

// Перебор происшедших в сети событий

 

 

 

//

 

 

 

М) It

 

ret = WSAEnumNetworkEvents(socks[index], events[index], 4ne); »IJ

 

if (ret == SOCKET.ERROR)

 

 

 

 

aale

pnntf("WSAEnumNetworkEvents() failed: Xd\n", WSAGetLastErrorO);

return;

// Данные для чтения

if ((ne INetworkEvents & FD.READ) == FD_READ)

wbuf.buf = databuf,

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

382

ЧАСТЬ II

Интерфейс прикладногсЯЦрограммиротния Winsock

 

 

 

 

Листинг 12-1.

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

..«чтих

 

Л

июни.

 

 

1-

-ttm№<

Ш!

 

«те

 

 

if (ne.iErrorCode[FD_READ_BIT])

 

 

 

isOci

 

 

printf("FO_READ error: Xd\n",

 

 

 

 

 

 

ne.iErrorCode[FD_READ_BIT]);

-bAtvo

••

TJctud

 

 

else

 

 

 

 

. (do

p+

 

printf("FD_READ\n");

 

 

О_вЬ«)

 

 

dwFlags = 0;

 

 

 

•-<; tnuootdo) U

 

ret =WSARecv(socks[index], &wbuf, 1, &dwBytesRecv,itft * *no<Jd

 

 

 

 

&dwFlags, NULL, NULL);

 

 

 

 

 

 

if (ret == SOCKET_ERROR)

 

 

j,

J;

;0 muJei

 

printf("WSARecv() failed: Xd\n", WSAGetLastErrorO);

 

 

 

 

 

return;

*

 

 

',

 

 

wbuf.len = dwBytesRecv;

 

 

 

 

 

 

 

 

 

printf("Read: %d bytes\n", dwBytesRecv);

 

>

втв

V

//

Может записывать данные; здесь

никакие

действия

не

предпринимаютздхоо

л

 

if ((ne.lNetworkEvents & FD_WRITE) == FD_WRITE)

 

 

 

 

 

{

 

 

 

 

 

 

 

 

\\

 

 

if (ne.iErrorCode[FD_WRITE_BIT])

 

 

 

 

F4,/iev3tneJ:I3eIbnBH bxov

 

 

printf("FD_WRITE error: Xd\n",

 

 

 

 

 

 

 

 

ne.iErrorCode[FD_WRITE_BIT]);

 

 

;m

 

 

 

 

else

 

 

 

 

 

,-f»eO*]tudeJRb

 

 

 

printf("FD_WRITE\n");

 

 

 

 

 

 

 

 

// Клиент закрыл соединение. Закрываем сокет с

 

 

 

 

 

// и очищаем структуры данных.

 

 

 

jm

 

j n i

 

 

/ /

 

 

 

 

 

 

Ц

 

 

 

if

((ne . lNetworkEvents &

FD_CLOSE)

==

FD.CLOSE)

 

 

 

 

 

{

 

 

i

wt

о s

х«йЬР»а«очл

ччввчвП \\

 

 

 

i f (ne.iErrorCode[FD_CLOSE_BIT])

 

 

 

 

\ \

 

 

 

printf("FD_CLOSE

e r r o r : J!d\n",w|j8H3Oi)eJneV1

 

 

 

 

 

ne.iErrorCode[FO_CLOSE_BIT]);

{Я0Я

 

 

 

 

 

else

 

 

 

 

 

 

>

 

 

 

pnntf("FD_CLOSE

. . . \ n " ) ;

.6» ()s?n«v3)!iowj'

'А8У("

• Utq

 

 

 

closesocket(socks[index]);

 

 

iCO^o-

Jit

 

 

 

 

WSACloseEvent(events[index]);

 

 

 

 

 

i j e i

 

 

 

 

 

 

 

 

 

 

<

 

 

 

socks[index] = INVALID_SOCKET;

 

 

 

 

 

 

 

 

 

//

 

 

 

 

 

 

 

 

 

//Удаляем элемент клиентского сокета из массива и

//сдвигаем оставшиеся элементы к началу массива.

for(i = index; i < MAX_C0NN - 1;

 

Г Л А ВА 12

Качество обслуживания

383

Листинг 12-1.

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

,

. . .

 

socks[i] = socks[i + 1];

 

 

\\

 

nConns-;

»'

 

«ей

S\

 

}

 

 

i«qr

 

^ II Получено

событие FD_QOS. Это может иметь

разные значения.

 

\\

 

if ((ne.lNetworkEvents & FD_QOS) == FD.QOS)

char

 

ia

 

 

 

 

 

 

 

buf[QOS_BUFFER_SZ];

 

 

 

 

 

 

 

 

 

 

 

QOS

 

 

 

 

 

 

 

 

 

 

*lpqos

 

=

 

NULL;

 

 

 

 

 

 

 

 

s

 

 

 

 

 

DWORD

 

 

 

 

 

 

 

 

 

 

dwBytes;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

\\

 

i f

( n

e

.

i

E

r

r

o

r

C

o

d

e

[

F

D

_

Q

O

S

_

B

I

T

]

)

 

 

 

 

J

q e o o A

b P K

i a v

i B

 

 

 

 

p

r

i

n

t

f

(

"

F

D

.

Q

O

S

 

e

r

r

o

r

:

 

X

d \

n

"

,

 

 

 

 

 

 

 

 

 

'

\

^

 

 

 

 

n

e

.

i

E

r

r

o

r

C

o

d

e

[

F

D

_

Q

O

S

_

B I

T ]

) ;

 

 

 

 

 

 

• &

> . - w . - i

n O \

\

3i else

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'"

'""'

1%Щ4

*&!№( о,.

\\

 

 

G*

printf("FD_QOS\n");

 

 

 

 

 

 

 

 

 

 

 

 

 

**

 

к

'е<»м>,

\\

 

»

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

^ t

 

 

тес,

\\

lpqos

 

=

 

(QOS

 

Obuf;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

«a**

 

 

,

'tie

\\

 

**'' lpqos->ProviderSpecific.buf =

 

&buf[sizeof(QOS)];

•**

 

 

 

 

0-

 

lpqos->ProviderSpecific.len

=

 

sizeof(buf)

-

sizeofCOW);

 

 

 

 

\\

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

w

 

ret = WSAIoctl(socks[index],

 

SIO.GET.QOS,

NULL, О,

 

 

 

 

ь

 

 

 

 

 

 

buf,

 

QOS.BUFFER.SZ,

&dwBytes,

NULL,

NULL);

«>*-

 

на

 

'

v

if

(ret

 

==

 

SOCKET.ERROR)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

printf("WSAIoctl(SIO_GET_QOS) failed M^J4,,ь

 

 

 

.-'I

 

1J

 

 

 

 

 

WSAGetLastErrorO);

 

 

 

 

 

 

 

I 4U8A8WJ

 

 

 

i

 

 

 

return;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

>

 

 

 

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

,0>

 

 

 

 

#0

 

 

PrintQos(lpqos);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

;•-

 

<ШвЗА(ТЗ>

 

 

 

 

 

//

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

э я

 

 

//

Проверим,

 

 

имеется

 

ли

 

настройка

для

приема

только

событий

FD.QOS.я1

 

 

//

Если

 

это

 

так,

 

то

 

нужно

 

вызвать

QOS

на

соединении

сейчас;

иначе

 

 

 

//

клиент

 

никогда

 

не

 

получит

сообщение RESV.

 

 

 

 

 

 

 

 

if (iSetQos == SET_QOS_EVENT)

lpqos->ReoeivingFlowspec.ServiceType =

serverQos.ReceivingFlowspec.ServiceType;

 

ret = WSAIoctl(socks[index], SIO.SET.QOS, lpqos,

i

dwBytes, NULL, 0, AdwBytes, NULL, NULL);

if (ret == SOCKET.ERROR)

 

printf("WSAIoctl(SIO_SET_QOS) failed: Xd\n",

 

WSAGetLastErrorO);

 

return;

 

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

384

ЧАСТЬ II

Интерфейс прикладного программирования Winsock

 

,

Листинг 12-1.

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

 

 

;

 

II

 

 

 

 

 

I/ Изменить ISetQos,

чтобы не пришлось снова задавать QOS

Dtt

 

// при получении еще одного события FD_QOS

 

{

 

//

 

 

 

с омйиуп

 

lSetQos = SET_QOS_BEF0RE;

 

\

 

}

 

»JH

-<И£ ел)) П

 

return;

 

 

 

 

>

 

 

,

 

гоо

// Функция: SrvCondAccept

 

 

en) ft

II Описание.

 

 

 

 

//

Это условная функция для

WSAAccept. Поставщик службы QOS

 

//имеет ограничение: значения QOS, передаваемые сюда, не надежны,

// поэтому параметр SET_QOS_DURING бесполезен, если мы не вызовем

//SIO_SET_QOS с нашими значениями (в противоположность значениям,

// запрашиваемым клиентом, поскольку те значения должны быть

//возвращены в IpSQOS).

//Заметьте' если в Windows 98 значение IpSQOS отлично от NULL,

//вы должны задать некоторые значения QOS (с помощью SIO_SET_QOS)

//в условной функции, иначе функция WSAAccept не отработает.

mt CALLBACK

SrvCondAccept(LPWSABUF lpCallerld,

 

 

 

)

LPWSABUF lpCallerdata,

LPQOS IpSQOS, LPQOS lpGQOS,

 

 

 

LPWSABUF lpCalleeld,

LPWSABUF lpCalleeData,

GROUP

*g,

 

 

DWORD dwCallbackData)

 

 

 

 

j m u J M

DWORD

dwBytes

= 0 ;

 

 

 

 

SOCKET

s = (SOCKET)dwCallbackData;

 

,£»OMl)eoOJnJ"i4

SOCKADDR_IN client;

 

C-H<"'

* VurtJ,

 

 

lnt

ret;

 

 

 

'ioimen

твтн .«Nqeeo^fl \\

 

 

 

 

 

T ,XJt1 OT«

NftOi

\\

if (nConns == MAX_C0NN)

 

-аюями

тнвкйя \\

return CF_REJECT;

 

 

 

 

 

\\

memcpy(&client, lpCallerId->buf, lpCallerId->len);

 

 

 

printf("Client request: Xs\n", inet_ntoa(client.sin_addr));

 

 

 

 

 

 

 

»o

 

 

if (lSetQos == SET_QOS_EVENT)

 

 

 

 

(

 

 

 

 

 

 

LA3W •» Jet.

printf("Setting

for event!\n");

 

 

asjyOwb

serverQos.SendingFlowspec.ServiceType |=

 

 

rei)

tJ:

 

SERVICE_NO_QOS_SIGNALING,

 

 

 

}

serverQos ReceivingFlowspec.ServiceType

|=

 

 

 

 

SERVICE_NO_QOS_SIGNALING;

 

 

 

 

ret = WSAIoctl(s,

SIO_SET_QOS, &serverQos,

 

 

 

sizeof(serverQos), NULL, 0, &dwBytes, NULL, NULL);

«<1фо Г Л А В А 12 Качество обслуживания

385

Листинг 12-1.

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

if (ret ==

SOCKET.ERROR)

{

»J

printf("WSAIoctl() failed: Xd\n"

WSAGetLastErrorO);

return

CF.REJECT;

return

CF_ACCEPT;

 

 

W8_80O_T38« coOJs> tt

 

re*

[0]э«>

 

 

 

 

 

ж

» • »

 

jl

m

 

 

г:

 

 

 

 

 

 

О

'

// Функция:

Server

 

 

 

 

 

//

 

 

 

 

 

q

//Описание'

//Эта подпрограмма сервера обрабатывает входящие клиентские соединения.

//

Сначала она задает прослушивающий сокет, затем задает Q0S

,

//в нужный момент времени и ожидает входящих клиентов и события. }-ц

//

 

 

7 с-П

void Server(SOCKET

s)

 

 

SOCKET

sc[MAX_CONN + 1 ] ;

JIlArt

тх

WSAEVENT

hAllEvents[MAX_C0NN+1];

 

"ЙЗ.ГЗХООЗ

SOCKADDR.IN

local,

 

 

 

client;

 

 

mt

clientsz,

 

 

 

ret,

 

 

 

I;

 

 

DWORD dwBytesRet;

WSANETWORKEVENTS ne;

// Инициализация массивов неверными значениями.

//

for(i = 0; l < MAX_C0NN+1;

hAHEvents[i] = WSA_INVALID_EVENT;

sc[i] = INVALID_SOCKET;

( Г) eIJtrtw

jH\o4ttBV(AC« • tei

«* Jet) tt

 

 

 

i

// Нулевой элемент массива будет прослушивающим

сокетом.

- • t))

//

 

 

 

hAllEvents[0] = WSACreateEvent();

 

 

sc[0]

= s;

 

\

nConns

= 0 ,

/3).

 

local.sin_family = AF_INET; local sin_port = htons(5150);

local sm_addr.s_addr = htonl(INADDR_ANY);

if (bind(s, (SOCKADDR *)&local, sizeof(local)) == SOCKET.ERROR)

см след стр

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

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

{

printf("bind() failed: Xd\n", WSAGetLMttErrorO);

 

 

^

)

 

 

return;

1>Ш

 

 

 

 

 

 

listen(s, 7);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

{

 

if (iSetQos == SET_Q0S_BEF0RE)

 

 

 

 

 

 

 

{

 

 

 

 

 

 

>MJ,

 

 

 

ret = WSAIoctl(sc[0], SI0_SET_Q0S, &serverOos,

 

 

 

 

i

 

sizeof(serverQos), NULL, 0, &dwBytesRet, NULL, NULL);

 

 

 

if (ret == SOCKET_ERR0R)

 

 

 

 

 

 

 

 

 

printf("WSAIoctl(SIO_SET_QOS) failed:

Xd\n",

j

 

 

 

 

 

WSAGetLastErrorO);

 

1

 

 

.экквзмпО

\

 

return;

в <

 

 

 

l

"М)пдоп exfi

\v

 

}

vr,

 

 

 

 

.jfo

eiweHO

 

 

printf("Set QOS on listening socket:\n");

 

 

 

»<• Лингун в

 

 

PrintQos(&serverQos);

 

 

 

 

 

>,

 

4

if

(WSAEventSelect(sc[O], hAHEvents[0],

FD_ACCEPT) ==

 

 

 

ТЗЯ00 '

 

 

S0CKET_ERR0R)

 

 

 

 

 

4. TH3V1A-'.

 

{

 

 

 

 

 

 

MI_»fl0AX00s;

 

 

printf("WSAEventSelect()

failed: Xd\n",

WSAGetLastErrorO);

 

 

 

return;

 

 

 

 

 

 

Jnt

 

while (1)

 

 

 

 

 

 

0Jv8w6

 

{

 

 

 

- зти

 

 

 

ret = WSAWaitForMultipleEvents(nConns+1, hAHEvents,

FALSE,

 

 

 

WSA_INFINITE, FALSE);

 

 

 

 

 

 

 

 

 

if (ret == WSA_WAIT_FAILED)

 

 

 

 

 

 

 

 

{

 

 

Ц > jt ;O «

 

 

 

printf("WSAWaitForMultipleObject()

failed: Xd\n",

 

 

 

 

>

 

WSAGetLastErrorO);

 

 

 

 

 

 

 

 

return;

 

 

 

 

 

 

 

 

 

}

 

 

 

 

 

 

(

 

 

if ((i = ret - WSA_WAIT_EVENT_O) > 0)

// Сетевое событие клиента I \\

 

 

HandleClientEvents(sc,

hAHEvents,

i);

 

 

 

 

\\

 

else

 

 

 

 

 

 

 

 

 

{

 

 

"•

 

.

 

 

 

ret = WSAEnumNetworkEvents(sc[0],

hAllEvents[0],

 

 

»

t

 

 

&ne);

 

 

 

 

 

 

 

 

 

if (ret == S0CKET_ERR0R)

 

 

 

 

<1.'

 

 

 

{

 

 

 

 

 

 

 

 

printf("WSAEnumNetworkevents() failed: Xd\n", WSAGetLastErrorO);

return;

 

 

Г Л А ВА 12

Качество обслуживания

 

387

Листинг 12-1.

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

, ,

..

тнк lU

 

if ((ne.lNetworkEvents & FD_ACCEPT) ==

FD_ACCEPT)Jnno

 

 

,

{

 

iKI.en)

Tt

 

 

if (ne.iErrorCode[FD_ACCEPT_BIT])

>«nJh<}

 

 

,,

,'«

printf("FO_ACCEPT error: Xd\n",

 

i

,

 

ne.iErrorCode[FD_ACCEPT_BIT]);

 

{

 

м

else

 

,i

>.re.

 

 

printf("FD_ACCEPT\n");

 

 

{

ft

1clientsz = sizeof(client);

}sc[++nConns] = WSAAccept(s, (SOCKADDR *)&client, nut10 .м«;,м¥» \\

elf-, if u

 

&clientsz,

SrvCondAccept,

sc[nConns]);

 

Ipqo»

if

(sc[nConns]

== SOCKET_ERROR)

:»b->bj^,

 

{

 

 

 

ты *т&е< п.-,

 

 

printf("WSAAccept() failed: Xd\n",

•wwrede^o и чни*ъц«

\\

С 1 Ч Ш

 

WSAGetLastErrorO);

 

 

 

nConns-;

 

 

ГЭЛ008)}г»

client

 

return;

 

j*

 

 

hAHEvents[nConns] = WSACreateEvent();

 

 

n

Sleep(10000);

 

 

 

^

if in

if

(iSetQos == SET_QOS_AFTER)

 

J

 

{

{

 

 

 

^

 

pt

 

ret = WSAIoctl(sc[nConns],

SI0_SET_Q0S,

 

•t

 

&serverQos, sizeof(serverQos), NULL, 0, !<

 

}

 

&dwBytesRet, NULL, NULL);

•">

 

 

 

if (ret == S0CKET_ERR0R)

 

 

 

 

 

 

 

 

800

 

.,ir, '

 

printf("WSAIoctl()

failed:

Xd\n" втийтакйштжш

 

iir

 

 

WSAGetLastErrorO);

 

 

if

 

return;

 

Л',".

 

 

 

>

 

 

(JJUH •• tn»«2rt) TI

 

 

ret = WSAEventSelect(sc[nConns],

 

 

 

 

 

hAHEvents[nConns], FD_READ | FD_WRITE

 

 

 

FD_CLOSE | FD.QOS);

 

 

 

 

if (ret == S0CKET_ERR0R)

 

•M№

 

 

 

 

 

 

 

 

printf("WSAEventSelect() failed: Xd\n",

 

 

 

WSAGetLastErrorO);

 

 

 

 

 

return;

 

 

 

 

if (ne.lNetworkEvents 4 FD_CLOSE) printf("FD_CLOSEn");

if (ne.lNetworkEvents & FD_READ) pnntf("FD_READn");

if (ne.lNetworkEvents & FD.WRITE)

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