Главная страница

Программирование в сетях Windows. Э. Джонс, Д. Оланд


Скачать 2.88 Mb.
НазваниеЭ. Джонс, Д. Оланд
АнкорПрограммирование в сетях Windows.pdf
Дата12.10.2017
Размер2.88 Mb.
Формат файлаpdf
Имя файлаПрограммирование в сетях Windows.pdf
ТипКнига
#9346
страница6 из 50
1   2   3   4   5   6   7   8   9   ...   50
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'
p r i n t f ( " R e s e t A l l f a i l e d : 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;
к
1 }
I X
else
" {
i f
•.
%**<
ы
*
S l e e p ( d w D e l a y ) ; ( n - t ; r t J 8 r > 9
}
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++)
{
'} U •
{
на один укщтныА :ЦН&\уМА
•Ш) ft
}
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
, \\
else rAil f*il«

Г Л А В А 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;
}
©It
1
>
>
Sleep(dwDelay);
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); {
> <
> Mitt
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}v3rf
> 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: 'Xs
1
"
"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)
. // Прием данных, предназначенных для любого имени NetBIOS
// в таблице имен этого процесса 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
3 1
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

4AUI ь I Устаревшие сетевые API
А теперь перечислим все параметры командной строки, доступные для использования в программе-примере:
Ш /п:ту-патерегистрирует уникальное имя ту-пате\
Ж /g:group-name — регистрирует групповое имя group -name;
Ш /s — отправляет дейтаграммы (по умолчанию, в примере дейтаграммы
принимаются);
/с:п — отправляет или получает п дейтаграмм;
/r:receiver — определяет NetBIOS-имя для отправки дейтаграммы;
Ш /Ъ — использует широковещательную посылку дейтаграмм;
Ж /а — принимает данные для любого имени NetBIOS (присваивает полю
ncbjium значение OxFF);
Ш /1:п — выполняет все операции только на номере LANA n (по умолчанию все команды отправки и приема выполняются для всех номеров LANA);
/d:n — ждет п миллисекунд между отправками.
Для выполнения третьей команды запустите несколько клиентов на раз- ных компьютерах. Она иллюстрирует случай, когда один сервер посылает одно сообщение группе, и каждый член группы, ожидающий данные, полу- чит это сообщение.
Также попробуйте различные комбинации перечисленных команд с па- раметром командной строки /1-х, где х — действительный номер LANA. Этот параметр переключает программу из режима выполнения команд на всех номерах LANA в режим выполнения команд только на конкретном номере
LANA. Например, команда Nbdgram /n:CLIENT01 /1:0 заставит приложение слушать входящие дейтаграммы только на LANA 0 и игнорировать любые данные, поступающие на какой-либо другой номер LANA.
Параметр /а имеет смысл только для клиентов. Этот флаг заставляет ко- манду получения принимать входящие дейтаграммы, предназначенные для любого имени NetBIOS, которое зарегистрировано процессом. В нашем при- мере это не имеет особого значения, так как клиенты регистрируют только одно имя, но вы можете по крайней мере посмотреть, как это должно выг- лядеть в коде. Попробуйте изменить код так, чтобы он регистрировал имя для каждого параметра /п-.пате в командной строке. Запустите сервер с фла- гом получателя, заданным только для одного из имен, зарегистрированных клиентом. Клиент получит данные, несмотря на то, что команда NCBDGRECV
не обращается явно к конкретному имени.
Дополнительные команды NetBIOS
Все рассмотренные нами команды так или иначе относятся к установлению сеанса, отправке или получению данных через сеанс или дейтаграмму. Но есть несколько команд, предназначенных исключительно для обработки приема информации: команда опроса состояния адаптера (NCBASTAT) и ко- манда поиска имени (NCBFJNDNAME). Мы рассмотрим их, а затем перейдем s r

Г Л А В А 1 Интерфейс NetBlUb к программному сопоставлению номеров LANA протоколам — хотя это не функция NetBIOS, но в справочных целях ознакомиться с ней полезно.
Проверка состояния адаптера (команда NCBASTAT)
Команда опроса состояния адаптера полезна для получения информации о локальном компьютере и его номерах LANA Это единственный способ про- граммно выяснить МАС-адрес компьютера из Windows 95 и NT 4. Функции IP
Helper, появившиеся в Windows 2000 и Windows 98 (см. приложение А), предо- ставляют более универсальный интерфейс для выяснения МАС-адреса.
Команда и ее синтаксис довольно просты, но то, какие данные будут воз- вращены, зависит от способа вызова функции. Команда опроса состояния адаптера возвращает структуру ADAPTER_STATUS, сопровождаемую рядом структур NAME_BUFFER. Эти структуры определены следующим образом:
typedef struct _ADAPTER_STATUS {
UCHAR
UCHAR
UCHAR
UCHAR
UCHAR
WORD
> « WORD
WORD
WORD
WORD
DWORD
DWORD
WORD
WORD
WORD
WORD
DWORD
WORD
WORD
WORD
WORD
WORD
WORD
WORD
WORD
WORD
WORD
> ADAPTER
adapter_address[6];
rev_major;
reservedO;
adaptsr_type;
revjninor;
duration;
frmr_recv;
frmr_xmit;
iframe_recv_err;
xmit_aborts;
xmit_success;
recv_success;
iframe_xmit_err;
recv_buff_unavail;
t1_timeouts;
ti_timeouts;
reservedi;
free_ncbs;
max_cfg_ncbs;
max_ncbs;
xmit_buf_unavail;
max_dgram_size;
pending_sess;
max_cfg_sess;
max_sess;
max_sess_pkt_size;
name_count;
STATUS, *PADAPTER_STATUS;
typedef struct _NAME_BUFFER {
UCHAR name[NCBNAHSZ];
UCHAR name_num;
UCHAR name_flags;
} NAME.BUFFER, *PNAME_BUFFER;
.IK 4'f <

y o i з р е в ш и е с е т е в ы е M K I
Поля, представляющие наибольший интерес: МАС-адрес (adapter_ad-
dress), максимальный размер дейтаграммы (jnax_dgram_size) и максималь- ное количество сеансов (max_sess). Кроме того, поле name count сообщает,
сколько было возвращено структур NAME_BUFFER. Максимальное количество
NetBIOS-имен на номер LANA — 254, так что вы можете обеспечить доста- точно большой буфер для всех имен или вызвать команду опроса состояния адаптера с полем ncbjength, равным 0. Функция Netbios по завершении вы- дает необходимый размер буфера.
Поля, необходимые для вызова команды NCBASTAT-. ncb_command, ncb_
buffer, ncbjength, ncbjananum и ncbjzallname. Если первый символ поля
ncb_callname — звездочка ('), команда проверки состояния выполняется, но возвращает только NetBIOS-имена, добавленные вызывающим процессом.
Впрочем, если вы вызываете Netbios с командой опроса состояния адаптера,
добавляете уникальное имя к таблице имен текущего процесса, а затем ис- пользуете это имя в поле ncb_callname, все NetBIOS-имена, а также все име- на, зарегистрированные системой, добавляются в таблицу имен локального процесса. Вы можете также проверить состояние адаптера не с того ком- пьютера, где выполняется команда. Для этого задайте в поле ncb_callname
тля удаленной рабочей станции.
ПРИМЕЧАНИЕ Помните, что во всех именах компьютеров Microsoft
1б-му байту присваивается значение 0. Кроме того, они дополняются пробелами до фиксированной длины.
Приведенная в качестве примера простая программа — Astat.c, проверя- ет состояние всех LANA. Кроме того, при использовании флага /1:LOCAL-
NAME эта команда выполняется на локальном компьютере, но выдает пол- ную таблицу имен. Флаг /r:REMOTENAME инициирует удаленный опрос для указанного имени компьютера.
При использовании команды, проверяющей состояние адаптера, нужно учитывать некоторые моменты. Во-первых, у компьютера с несколькими адаптерами будет несколько МАС-адресов. Так как NetBIOS не позволяет вы- яснить, к которым адаптерам и протоколам привязан LANA, разбираться в возвращенных значениях придется самостоятельно. Кроме того, если уста- новлена служба удаленного доступа (Remote Access Service, RAS), система вы- делит номера LANA и для удаленных соединений. Пока соединения RAS не- активны, проверка состояния адаптера на этих LANA вернет нулевой МАС- адрес. Если установлено соединение RAS, МАС-адрес будет соответствовать тому который служба RAS назначает всем своим виртуальным сетевым уст- ройствам.
Наконец, проверку состояния удаленного адаптера вы должны выполнять по общему для обоих компьютеров транспортному протоколу. Например,
системная команда Nbtstat (версия NCBASTATрдя командной строки) выпол- няет опрос только по TCP/IP. Если на удаленном компьютере нет TCP/IP, ко- манда не будет выполнена.

1   2   3   4   5   6   7   8   9   ...   50


написать администратору сайта