Программирование в сетях Windows
.pdf380 ЧАСТЬ 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) |
4» |
<v« v\ |
|||||
{ |
status = (RSVP_STATUS_INFO *)objhdr; |
|
|
|
|||
|
|
|
|
||||
|
if (status->StatusCode & dwFlags) |
|
|
|
|||
|
return 1; |
|
|
|
|
|
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;
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);
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;