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

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

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

38

ЧАСТЬ I

Устаревшие сетевые API

 

Листинг 1-5.

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

 

 

NCB

 

neb;

 

 

ZeroMemory(&ncb, sizeof(NCB));

 

 

ncb.ncb_command = NCBDGSEND;

 

 

ncb.ncb_lana_num = lana;

 

 

neb.ncb_num = num;

 

 

ncb.ncb_buffer

=

(PUCHAR)buffer;

'

 

ncb.ncb_length =

buflen;

 

 

 

 

 

 

 

Л

memset(ncb.ncb_callname, ' ', NCBNAMSZ);

 

strncpy(ncb.ncb_callname, recipient,

strlen(recipient));

ywn <•<•»«<>#

 

 

 

 

 

ч

if

(Netbios(&ncb)

!= NRC_G00DRET)

 

 

{

printf("Netbios: NCBDGSEND failed: Xd\n", neb.ncb_retcode); return ncb.ncb_retcode;

}

return NRC_G00DRET;

//Функция: DatagramSendBC

//Описание:

//Посылает широковещательную дейтаграму по конкретному номеру LANA с

//данного номера имени. Также указаны буфер данных и количество

//отправляемых байт.

//

int DatagramSendBC(int lana, int num, char «buffer, mt buflen)

{

NCB neb;

ZeroMemory(&ncb,

sizeof(NCB));

 

ncb.neb_command

=

NCBDGSENDBC;

{

neb.ncb_lana_num

= lana;

ncb.ncb_num = num;

 

ncb.ncb_buffer

=

(PUCHAR)buffer;

7

ncb.ncb_length

=

buflen;

 

&Q :m '*

if (Netbios(&ncb) 1= NRC.GOODRET)

{

printfC'Netbios: NCBDGSENDBC failed: Xd\n", ncb.ncb.retcode); return ncb.ncb_retcode;

}

return NRC.GOODRET;

J

.Jflftt!

 

 

 

 

 

 

 

 

 

 

 

Г Л А ВА 1

Интерфейс NetBIOS

39

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

 

 

 

 

 

 

 

II

Функция:

DatagramRecv

 

 

 

 

 

 

 

 

 

//

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//

Описание:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

//

Получает

дейтаграмму

на

данном

номере LANA

направленную по имени,

 

//

представленному

параметром

num.

 

Данные копируются в предоставленный буфер.

 

//

Если hEvent

не

0,

вызов

приема

выполняется

асинхронно

 

//

с указанным

описателем события.

 

Если параметр

num

равен OxFF, слушает

 

//

дейтаграммы,

предназначенные для

любого

имени

NetBIOS,

 

//

зарегистрированного

процессом.

 

 

 

 

 

 

 

int

DatagramRecv(PNCB

pncb,

int lana, int

num,

char

«buffer,

 

 

 

 

int

buflen,

HANDLE

hEvent)

 

 

 

 

{

ZeroMemory(pncb, sizeof(NCB)); if (hEvent)

{

pncb->ncb_command = NCBDGRECV | ASYNCH; pncb->ncb_event = hEvent;

}

 

else

 

pncb->ncb_command = NCBDGRECV;

 

pncb->ncb_lana_num = lana;

 

pncb->ncb_num = num;

 

pncb->ncb_buffer = (PUCHAR)buffer;,^)

 

pncb->ncb_length = buflen;

„ s , a j A i ! ч1

if (Netbios(pncb) != NRC_G00DRET)

 

{

 

printf("Netbos: NCBDGRECV failed:

И\п", pncb->ncb_retcode);

return pncb->ncb_retcode;

 

}

I8J*.

return NRC_GOODRET;

,|

//Функция: DatagramRecvBC

//Описание:

//

Получает широковещательную

дейтаграмму на данном номере LANA.

// Данные копируются в предоставленный

буфер. Если hEvent не равно О,

//

вызов приема выполняется асинхронно с указанным

//

описателем события.

 

 

 

//

 

 

 

 

int

DatagramRecvBC(PNCB

pncb,

int lana,

int num, char «buffer,

 

int

buflen,

HANDLE hEvent)

ZeroHemory(pncb, sizeof(NCB)); if (hEvent)

,"n/bt:to9ix*1 см.след.стр.

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

{

pncb->ncb_command = NCBDGRECVBC | ASYNCH;

pncb->ncb_event = hEvent;

 

}

 

else

 

pnob->ncb_comrnand = NCBDGRECVBC;

 

pncb->ncb_lana_num = lana;

*tt

pncb->ncb_num = nuin;

Ь >

pncb->ncb_buffer = (PUCHAR)buffer;

ы к ч

pncb->ncb_length = buflen;

 

 

tni

'if (Netbios(pncb) != NRC_G00DRET)

*{

printf("Netbios: NCBDGRECVBC failed: Xd\n", pncb->ncb_retcode); return pncb->ncb_retcode;

return NRC_G00DRET;

II Функция: main

 

 

 

 

 

 

 

 

 

 

 

 

//

 

 

 

 

 

 

 

 

 

 

 

 

%

 

II Описание:

 

 

 

 

 

 

 

 

 

 

 

 

 

// Инициализирует интерфейс NetBIOS,

выделяет ресурсы,

а

затем отправляет илщ

 

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

 

 

 

 

I

//

 

 

 

 

 

 

 

 

 

 

 

 

 

 

int main(int argc,

char *»argv)

 

 

 

 

 

 

W;

4

 

i

 

 

 

 

 

 

 

 

 

 

 

 

)

 

LANA_ENUM

lenum;

 

 

 

 

 

 

»«")t--

,

 

 

int

i,

j ;

 

 

 

 

 

 

•*}

 

'*'

 

 

char ' ''

szMes9age[MAX_DATAGRAM_SIZE],

 

 

 

 

 

{

 

 

 

szSender[NCBNAMSZ

+ 1];

 

 

 

< ЗЙТО8.,/

 

'«Jei

 

DWORD

«dwNufli =

NULL,

 

 

 

 

 

 

 

 

 

{

 

 

dwBytesRead,

 

 

 

 

 

 

 

 

 

 

 

 

dwErr;

 

 

 

 

 

 

 

 

\\

 

 

 

 

 

 

'"

 

 

 

}ЧуовЯя»чв*гд5

:ймдамуФ

\\

ValidateArgs(argc, argv);

 

 

 

 

 

 

 

 

 

\\

//

 

 

 

 

 

 

 

 

 

 

:mmomO \\

II Перечисление и сброс номеров LANA

 

 

штв)в»*вж><}м»в

-вР^уноП

\\

//

 

 

 

 

 

 

»п

в

изт«у«1«10)«

*

->Д \\

 

if

((dwErr

= LanaEnum(&lenum)) !=

NRC_G0ODRET)

 

iWwwrtfa г iNtjf;

ta

\\

{

 

 

 

 

 

 

 

 

 

. «rrwdoo

mm i

 

i \\

 

printf("LanaEnum

f a i l e d :

Xd\n",

dwErr);

 

 

 

 

 

 

\,

 

return

1;

 

 

 

 

 

 

•&}№%'

 

,.m

 

tnl

}

 

 

 

 

 

 

 

 

, й

int

 

 

 

 

if

((dwErr

= ResetAlK&lenum,

(UCHAR)MAX_SESSIONS,

 

'

 

 

 

 

J

 

(UCHAR)HAX_NAMES,

FALSE))

1=

NRC.GOODRET)

otie

,dor

.me,*1

 

 

{

 

 

 

 

 

 

 

 

 

 

s.v9'

 

 

 

printf("ResetAll

failed:

Xd\n",

dwErr);

 

 

 

 

 

 

 

Г Л А ВА 1 Интерфейс NetBIOS

41

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

//Этот буфер содержит номер добавленного к каждому номеру LANA

//NetBIOS-имени

//

dwNum = (DWORD .)GlobalAlloc(GMEH_FIXED | GMEM_ZEROINIT, sizeof(DWORD) * lenum.length);

if (dwNum == NULL)

{

printf("out of memory\n"); return 1;

//

Если мы

собираемся работать только

на

одном номере LANA,

имя регистрируется

//

только

на этом номере LANA,

иначе

имя

регистрируется на

всех

//

номерах

LANA

 

 

 

 

//

 

 

 

 

 

 

if

(bOneLana)

П \i

 

 

 

{

 

 

 

 

 

 

if (bUniqueName)

AddName(dwOneLana, szLocalName, &dwNum[0]);

else

AddGroupName(dwOneLana, szLocalName, &dwNura[0]);

>

else

{

for(i = 0; i < lenum.length; i++)

{

if (bUniqueName)

AddName(lenum.lana[i], szLocalName, &dwNum[i]); else

AddGroupNarne(lenum.lana[i], szLocalName, &dwNum[i]);

//

Отправка

дейтаграмм

 

 

//

 

 

 

 

 

 

if

(bSender)

 

 

*

{

 

 

 

 

 

 

 

//

Отправка с использованием

широковещания

.ще-

 

II

 

 

 

 

 

 

if

(bBroadcast)

 

ti

 

{

 

 

 

 

 

 

 

if

(bOneLana)

 

 

 

n

<

 

 

 

 

 

 

 

//

Широковещательная

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

только на одном номере

 

 

 

//

LANA

и

 

.след.стр.

Листинг 1 -5.

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

 

 

 

 

 

 

 

 

 

for(j = 0; j < dwNumDatagrams; ]++)

 

 

 

 

 

 

wsprintf(szMessage,

 

 

 

 

 

 

 

 

 

"[J(03d] Test broadcast datagram", j);

 

 

 

 

if

(DatagramSendBC(dwOneLana,

dwNum[0],

 

 

 

 

 

 

szMessage, strlen(szMessage))

 

 

 

 

 

 

 

!= NRC_G00DRET)

 

 

 

 

 

 

 

 

 

return 1;

 

 

 

 

 

 

 

 

 

Sleep(dwDelay);

 

 

 

 

f j j

t

 

 

 

'

 

 

 

 

 

 

 

/

 

}

 

 

 

,{

г

МИР

To 'TUO*"

11

 

л

else

»

,!)

 

 

 

 

•(

,|

 

<

 

 

 

 

 

 

 

 

{

 

 

// Широковещательная отправка сообщения на каждом номере LAN^

 

 

 

// на

локальной машине

 

 

 

 

 

, ,3 ^

 

 

//

 

 

 

 

 

 

 

иг \\

 

 

for(j = 0; j < dwNumDatagrams;

j++)

 

 

 

, ,-,н ^

 

 

{

 

 

 

 

 

 

 

\\

 

 

for(i = 0; i < lenum.length;

i++)

 

l

s®r,l'4) 1i

 

 

 

wsprintf(szMessage,

 

 

 

 

 

} ^

 

 

 

"[)(03d] Test broadcast datagram", j);

 

 

 

 

 

if (DatagramSendBC(lenum.lana[i], dwNum[i],

w , £ e

 

 

 

 

szMessage,

strlen(szMessage))

 

S M # >

»ЯН

 

>¥*<•*

1= NRC_GOODRET)

*®хя* n

 

 

 

{

 

 

 

return 1;

 

 

 

 

 

 

 

 

 

S l e e p ( d w D e l a y ) ;

( n - t

 

; r t J 8 r > 9

 

 

 

 

к

1 }

IX else

"{

if

}

 

 

 

 

 

'} U

m m

t n n m

t t

 

• 8

A t j a t t a l

e u t *

{

( b O n e L a n a )

 

 

 

 

 

// Отправка направленного сообщения на один укщтныА :ЦН&\уМА

•.for(j = 0; j < dwNumDatagrams; j++)

%**<

ы* {

 

 

 

 

 

wsprintf(szMessage,

 

«

о «ж

 

- L

"[X03d] Test directed datagram",

J>;

 

 

if

(DatagramSend(dwOneLana,

dwNum[0],

(jp,

 

 

Ui

szRecipientName, szMessage,

 

 

 

1

strlen(szMessage)) !=

NRC.GOODRET)

,

 

 

return 1;

 

 

 

 

Sleep(dwDelay);

4 H C

, \\

•Ш) ft

}

else

rAil f*il«<J: 1<j\n*

Г Л А ВА 1 Интерфейс NetBIOS

43

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

//Отправка прямого сообщения на каждом номере LANA на

//локальной машине

for(j = 0; j < dwNumDatagrams;

{

for(i = 0; i < lenum.length;

wsprintf(szMessage,

"[K03d] Test directed datagram", j); printf("count: Xd.JSd\n", j,i);

if (DatagramSend(lenum.lana[i], dwNum[i], szRecipientName, szMessage, strlen(szMessage)) != NRCJ300DRET) return 1;

}Sleep(dwDelay);

©It

 

>

 

1

>

 

 

else

 

//

Прием дейтаграмм

{

 

 

 

NCB

 

*ncb=NULL;

 

char

 

««szMessageArray

= NULL;

HANDLE

*hEvent=NULL;

 

DWORD

dwRet;

 

// Выделение массива структур NCB для передачи каждому приемнику

//на каждом LANA

neb = (NCB *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(NCB) « lenum.length);

//Выделение массива буферов входящих данных

//

szMessageArray = (char ••)GlobalAlloc(GMEM_FIXED, sizeof(char *) • lenum.length);

for(i = 0; l < lenum.length; i++)

szMessageArray[i] = (char *)GlobalAlloc(GMEM_FIXED, MAX_DATAGRAM_SIZE);

//

//Выделение массива описателей событий для

//асинхронных приемов

//

hEvent = (HANDLE OGlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(HANDLE) • lenum.length);

for(i = 0; i < lenum.length; i++)

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

44

ЧАСТЬ I Устаревшие сетевые API

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

hEvent[i] = CreateEvent(O, TRUE, FALSE, 0);

if (bBroadcast)

{

if (bOneLana)

{

//

Синхронный

широковещательный

прием

 

//

на

одном указанном номере LANA

 

/ /

 

 

 

' * • »

 

for(j

= 0; j < dwNumOatagrams;

 

 

 

if (DatagramRecvBC(&ncb[O],

dwOneLana,

dwNum[0],

 

 

szMessageArray[O], MAX_DATAGRAM_SIZE,

 

 

NULL) != NRC_GOODRET)

 

'***

 

 

return

1;

 

 

 

FormatNetbiosName(ncb[0].ncb_callnarne,

szSender);

"printf("X03d [LANA Xd] Message: 'Xs' "

 

 

"received from:

Xs\n",

j,

 

 

 

 

 

*

ncb[O].ncb_lana_num, szMessageArray[O],

{

 

 

 

szSender);

 

 

 

 

 

 

 

>

 

 

 

 

 

 

 

 

 

 

 

<

>

 

 

 

 

 

 

 

 

 

 

 

 

else

 

 

 

 

 

 

 

 

 

 

 

 

{

 

 

 

 

 

 

 

 

 

 

8ОИ

 

// Асинхронный широковещательный прием на каждом

 

з

/I

доступном

номере LANA.

Для

каждой

успешной

команды

 

 

//

печатается

сообщение,

иначе

команда отменяется.

 

 

for(]

= 0;

j

< dwNumDatagrams;

 

 

 

 

 

 

for(i =

0;

i < lenum.length; i++)

 

 

\\

 

 

dwBytesRead = MAX_DATAGRAM_SIZE;

 

 

 

 

 

if

(DatagramRecvBC(&ncb[i],

lenum.lana[i],

\\

 

 

 

dwNumfi],

szMessageArray[i],

 

,кмцЛ

\\

 

 

 

MAX_DATAGRAM_SIZE, hEvent[i])

 

"

* $

 

 

 

!=

NRC_GOODRET)

 

 

 

 

 

 

 

 

return 1;

 

 

 

 

 

 

 

 

dwRet = WaitForMultipleObjects(lenum.length,

 

 

 

 

hEvent,

FALSE,

INFINITE);

 

 

 

 

 

if

(dwRet

== WAIT_FAILED)

 

 

 

\\

 

 

<

 

 

 

 

 

 

 

 

 

l \ \

 

 

 

pnntfC'WaitForMultipleObjects failed:

Xd\n",

t \\

 

 

 

 

GetLastErrorO);

 

 

 

 

\\

 

 

return

1;

 

 

 

 

 

 

K}v3

 

>

 

 

 

 

 

 

 

 

nl$

 

 

 

for(i = 0;

 

i < lenum.length;

i++) *, ,.u •• I

,0

 

 

 

 

 

Г Л А ВА 1

Интерфейс NetBIOS

45

Листинг 1 -5.

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

 

 

 

 

 

 

 

if (ncb[i].ncb_cmd_cplt == NRCJPENDING)

 

 

 

 

Cancel(&ncb[i]);

 

 

 

 

 

 

 

else

 

 

 

 

 

 

 

{

 

 

 

 

 

 

 

ncb[i].ncb_buffer[ncb[i].ncb_length] = 0;

 

' AVfAJ eqe

 

FormatNetbiosName(ncb[i].ncb_callname,

 

 

 

 

szSender);

 

 

 

 

 

 

 

printf("X03d [LANA Xd] Message: 'Xs1 "

 

 

 

 

"received from:

Xs\n", j,

 

 

*

 

ncb[i].ncb_lana_num,

 

 

 

'

 

szMessageArray[i],

szSender);

 

 

f

 

}

 

 

 

 

 

 

 

ResetEvent(hEvent[i]);

 

 

 

 

 

K

}

 

 

 

 

 

 

 

>

 

 

 

 

 

m

}

 

 

 

 

 

 

 

}

 

 

 

 

 

 

 

else

 

 

 

 

 

 

 

{

 

 

 

 

 

 

 

if

(bOneLana)

 

 

 

 

 

{

 

 

 

 

 

 

 

 

// Блокирующий прием дейтаграмм на указанном

 

 

 

// номере LANA

 

 

 

 

 

 

//

 

 

 

 

 

*u

 

for(j

= 0; j < dwNumDatagrams;

]++)

 

 

 

if

(bRecvAny)

 

 

 

 

.

 

 

// Прием данных,

предназначенных для любого

имени NetBI

 

 

 

// в таблице имен этого процесса

 

 

 

 

if (DatagramRecv(&ncb[O], dwOneLana, OxFF,

 

 

 

 

szMessageArray[O], MAX_DATAGRAM_SIZE,

 

 

 

 

NULL) != NRC_GOODRET)

 

 

 

Sl

 

 

return 1;

 

 

 

 

 

 

}

 

 

 

 

 

j,

 

 

else

 

 

 

 

 

 

{

 

 

 

 

 

 

 

 

if (DatagramRecv(&ncb[O], dwOneLana,

 

 

 

 

dwNum[0],szMessageArray[O],

 

 

 

 

MAX_OATAGRAM_SIZE, NULL)

 

 

 

 

 

!= NRC_GOODRET)

 

 

 

 

 

 

 

return 1;

 

 

 

 

 

 

}

 

 

 

 

 

 

 

FormatNetbiosName(ncb[0].ncb.callnarne, szSender);

 

 

 

printf("X03d [LANA Xd] Message:

 

'Xs- "

 

 

 

 

"received from: Xs\n", j,

 

 

 

• .r

,

ncb[O].ncb_lana_num,

szMessageArray[O],

 

 

 

 

 

 

 

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

, м р е в ш и е сетевые A K I

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

else

// Асинхронный прием дейтаграмм на каждом доступном номере LANA.

//Для успешных команд печатаются данные,

//иначе команда отменяется.

for(j = 0;

2 < dwNumDatagrams; j

 

 

 

{

 

 

 

 

for(i = 0; i < lenum.length;

 

 

 

{

 

 

 

 

If

(bRecvAny)

 

 

 

 

// Прием данных, предназначенных для любойо

 

 

 

// NetBIOS в таблице имен этого процесса

 

{

 

//

 

 

tele

 

if (DatagramRecv(&ncb[i],

lenum.lana[i],

 

}

 

OxFF, szMes'sageArray[i],

 

i

 

MAX_DATAGRAM_SIZE, hEvent[i])

}

^

 

|= NRC_GOODRET)

 

 

 

 

return 1;

 

 

 

1 {

'ft

 

 

 

t

it (DatagramRecv(&ncb[l],

lenum.lana[i],

 

 

dwNum[l],szMessageArray[i], MAX_DATAGRAM_SIZE, hEvent[i]) |= NRC.GOODRET)

return 1;

,} ft»

'}

dwRet = WaitForMultipleObjects(lenum.length, hEvent, FALSE, INFINITE);

if (dwRet == WAIT_FAILED)

{

printf("WaitForMultipleObjects failed: Xd\n", GetLastErrorQ);

return 1;

for(i = 0; i < lenum.length;

i f ( n c b [ i ] . n c b _ c m d _ c p l t = = NRC_PENOING) iJV*"- C a n c e l ( & n c b [ i ] ) ;

e l s e

(

ncb[i].ncb_buffer[ncb[i].ncb_length] = 0; FormatNetbiosName(ncb[i].ncb_callname,

Г Л А В А 1 интерфейс Netbiob

4/

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

szSender);

printf("X03d [LANA Xd] Message: 'Xs' " "from: Xs\n", j, nob[i].ncb_lana_num, szHessageArray[i], szSender);

}

ResetEvent(hEvent[i]);

// Очистка

//

for(i = 0; i < lenum.length;

CloseHandle(hEvent[i]);

GlobalFree(szMessageArray[i]);

}

-f GlobalFree(hEvent);

f.GlobalFree(szMessageArray);

л>

//Очистка

•t

И

 

if (bOneLana)

 

DelName(dwOneLana, szLocalName);

x

else

31

f o r ( i = 0; i < lenum.length;

^

DelName(lenum.lana[i], szLocalName);

 

}

-t

GlobalFree(dwNum);

 

return 0;

}

 

Скомпилировав этот пример, выполните следующие тесты, чтобы понять, как работают дейтаграммы (табл. 1-2). В целях обучения запустите две копии приложений на разных компьютерах. Если вы запустите их на одном компьютере, они будут работать, но вы можете не увидеть некоторые важные моменты, так как в этом случае LANA для обеих сторон будут соответствовать одному и тому же протоколу.

Табл. 1-2. Команды вызова Nbdgram.c

Команда клиента

 

Команда сервера

.

 

 

 

 

 

Nbdgram /n:CLIENTO I

Nbdgram /s /n:SERVER01 /r-CLIENTO 1

 

Nbdgram /n:CLIENT01 /b

Nbdgram /s /n:SERVER01 /b

 

Nbdgram /g:CLIENTGROUP

Nbdgram /s /r.CLIENTGROUP

 

Nbdgram /g:CLIENTGROUP

Nbdgram /s /r.CLIENTGROUP