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

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


Скачать 2.88 Mb.
НазваниеЭ. Джонс, Д. Оланд
АнкорПрограммирование в сетях Windows.pdf
Дата12.10.2017
Размер2.88 Mb.
Формат файлаpdf
Имя файлаПрограммирование в сетях Windows.pdf
ТипКнига
#9346
страница23 из 50
1   ...   19   20   21   22   23   24   25   26   ...   50

ГЛАВА 8 Ввод-вывод в Winsock 241
Листинг 8-10. (продолжение)
closesocket(PerHandleData->Socket);
GlobalFree(PerHandleData);

GlobalFree(PerloData);
continue;
// Обслуживание завершившегося запроса ввода-вывода.
// Чтобы определить, какой запрос завершился,
// нужно просмотреть в данных операции поле OperationType.
if (PerIoData->OperationType == RECV_POSTED)
{
// Обработка принятых данных
// в буфере PerIoData->Buffer
// Отправка нового запроса ввода-вывода WSASend или WSARecv.
// В качестве примера отправим еще один асинхронный запрос WSARecvO
/' Flags = 0;
'" " // Настройка данных операции
^ I/ для следующего запроса перекрытого ввода-вывода
Г->ь ZeroMemory(&(PerIoData->Overlapped),
-< sizeof(OVERLAPPED));
нк PerIoData->DataBuf.len = DATA_BUFSIZE;
,st/ PerIoData->DataBuf .buf = PerIoData->Buffer;
ш
PerIoData->OperationType = RECV_POSTED;
w
WSARecv(PerHandleData->Socket,
&(PerIoData->DataBuf), 1, &RecvBytes,
f
'
1
" &Flags, &(PerIoData->Overlapped), NULL);
Последний момент, не отраженный ни в листингах 8-9 и 8-10, ни на при- лагаемом компакт-диске — корректное закрытие порта завершения. Это осо- бенно важно, если один или несколько выполняющихся потоков ведут ввод- вывод на нескольких сокетах. Главное — не освобождать структуру OVERLA-
PPED, пока выполняется перекрытый запрос ввода-вывода. Лучше всего вы- зывать функцию closesocket для каждого описателя сокета, тогда все опера- ции перекрытого ввода-вывода будут завершены. После закрытия всех соке- тов нужно завершить все рабочие потоки порта завершения. Отправьте каж- дому потоку специальный завершающий пакет функцией PostQueuedComp-
letionStatus, это заставит поток немедленно прекратить работу:
пи1и программирования vvinsocK
BOOL PostQueuedCompletionStatus(
HANDLE CompletlonPort,
DWORD dwNumberOfBytesTransferred,
DWORD dwCompletionKey,
LPOVERLAPPED lpOverlapped
);
Параметр CompletlonPort — объект порта завершения, которому нужно отправить завершающий пакет Параметры dwNumberOfBytesTransferred, dw-
CompletionKey и lpOverlapped позволяют задать значение, которое будет за- писано прямо в соответствующий параметр функции GetQueuedComple-
tionStatus Когда рабочий поток получит эти три параметра, он сможет оп- ределить, когда следует прекращать работу, на основе специального значе- ния, заданного в одном из трех параметров Например, можно передать 0 в параметре dwCompletionKey — рабочий поток интерпретирует это как инст- рукцию об окончании работы После закрытия всех рабочих потоков зак- ройте порт завершения, вызвав функцию CloseHandle, и безопасно выйдите из программы
Как повысить эффективность ввода-вывода
Существует несколько приемов, позволяющих увеличить эффективность вво- да-вывода через сокеты с использованием портов завершения Один из них — опытным путем подобрать размер буфера сокета, чтобы увеличить производительность и масштабируемость приложения Например, приложе- ние, которое использует один большой буфер и только один запрос WSARecv
вместо трех маленьких буферов для трех запросов WSARecv, будет плохо мас- штабироваться на многопроцессорных машинах, поскольку с одним буфером одновременно может работать только один поток Пострадает и производи- тельность если одновременно выполняется только одна операция приема,
драйвер сетевого протокола будет недостаточно загружен То есть если вам приходится ждать завершения WSARecv перед получением новых данных, про- токол будет простаивать между завершением WSARecv и следующим приемом
Существует еще один способ увеличить производительность — проана- лизируйте результаты использования параметров сокета SOSNDBUF и
SO_RCVBUF для управления размером внутренних буферов сокета Они по- зволяют приложению изменять размер внутренних буферов Если прирав- нять их к 0, Winsock будет напрямую использовать буфер приложения во время перекрытого вызова для передачи данных в стек протокола и обрат- но, уменьшая межбуферное копирование Следующий фрагмент показыва- ет, как вызывать функцию setsockopt для настройки параметра SOSNDBUF
int nZero = 0;
setsockopt(socket, SOL.SOCKET, SO_SNDBUF,
(char *)&nZero, sizeof(nZero)),
Заметьте нулевой размер буферов даст положительный эффект, только если несколько запросов ввода-вывода отправляются одновременно Под- робнее об этих параметрах сокета — в главе 9

Г Л А В А 8 Ввод-вывод в Winsock 243
Наконец, для соединений, где передаются небольшие порции данных,
производительность можно увеличить с помощью функции AcceptEx Это позволяет приложению обслужить принятый запрос и извлечь данные од- ним вызовом API-функции, исключив издержки от раздельных вызовов " функций accept и WSARecv При этом запрос AcceptEx обслуживается через порт завершения, так как AcceptEx использует структуру OVERLAPPED Функ- ция AcceptEx полезна, если планируется, что сервер будет обрабатывать не- большое количество транзакций приема-передачи после установления со- единения (как на Web-сервере) Если же приложение выполняет сотни и тысячи передач данных после установления соединений, реального увели- чения производительности не будет
В заключение заметим, что Winsock-приложения не должны применять
\Ут32-функции ReadFile и WnteFile для обработки ввода-вывода через порт завершения Хотя эти функции используют структуру OVERLAPPED и ошиб- ки не произойдет, функции WSARecv и WSASend лучше оптимизированы для обработки ввода-вывода в Winsock 2 Обращение к ReadFile и WnteFile ведет к множеству ненужных вызовов процедур системного ядра, переключений контекста и передачи параметров, что в итоге значительно снижает произ- водительность
Сравнение моделей ввода-вывода
Как же при проектировании приложения выбрать модель ввода-вывода'
У каждой из них свои достоинства и недостатки, и все модели сложнее в про- граммировании, чем простой ввод-вывод с блокировкой и несколькими по- токами Рассмотрим возможные решения для разработки клиентских и сер- верных приложений
Клиент
При разработке клиентского приложения, управляющего одним или не- сколькими сокетами, мы рекомендуем использовать модель перекрытого ввода-вывода или модель WSAEventSelect для увеличения производительнос- ти Впрочем, при разработке приложения Windows, работающего с сообще- ниями окна, модель WSAAsyncSelect может быть лучше, гак как сама опирает- ся на модель сообщений Windows, а ваше приложение уже содержит меха- низм обработки сообщений
Сервер
При проектировании сервера, обрабатывающего несколько сокетов одно- временно, рекомендуем модель перекрытого ввода-вывода Впрочем, если вы планируете, что сервер будет одновременно обрабатывать большое количе- ство запросов ввода-вывода, попробуйте использовать порты завершения
Резюме
Мы рассмотрели все модели ввода-вывода, доступные в Winsock Они позво- ляют приложению использовать ввод-вывод Winsock в соответствии со сво-

II интерфейс прикладного программирования vvinsocK
ими нуждами от простого ввода-вывода с блокировкой до быстрого ввода- вывода через порт завершения
В этой главе заканчивается обсуждение общих аспектов Winsock Мы го- ворили о доступных транспортных протоколах, атрибутах создания сокетов,
создании простых клиент-серверных приложений и прочих фундаменталь- ных понятиях Winsock
В главах 9- И будут рассмо грены специальные темы Winsock Следующая глава посвящена параметрам сокетов и командам управления вводом-выво- дом, регулирующим работу как сокетов, так и базовых протоколов

Г Л А В А
id I
i, '
Параметры сокета и команды управления вводом-выводом
Создав сокет, можно манипулировать его свойствами через параметры и команды управления вводом-выводом Некоторые из этих параметров про- сто возвращают информацию, но другие — влияют на поведение сокета в приложении Также воздействует на поведение сокета ioctl-команды В этой главе обсуждаются четыре функции Winsock getsockopt, setsockopt, ioctlsocket
и WSAIoctl У каждой множество команд, в большинстве своем плохо докумен- тированных Мы рассмотрим обязательные и дополнительные параметры для каждой функции, а также поддерживающие их платформы Каждый па- раметр предположительно работает на всех платформах Win32 (Windows
СЕ, 95, 98, NT и 2000), если иное не оговорено Поскольку интерфейс Win- sock 2 дос гупен не на всех платформах, ioctl-команды и параметры из его состава не поддерживаются в Windows СЕ или Windows 95 (кроме случаев,
когда для Windows 95 установлено обновление Winsock 2) Напомним, что
Windows СЕ не поддерживает никакие параметры, не относящиеся к TCP/IP
Большинство ioctl-команд и параметров описаны в файлах Winsockh или Winsock2 h (в зависимости от их специфичности для Wmsock 1 или
Winsock 2) Впрочем, некоторые параметры специфичны для поставщика
Microsoft или для определенного транспортного протокола Расширения
Microsoft описаны в Winsock h и Mswsock h Расширения поставщиков транс- порта описаны в их собственных заголовочных файлах для каждого прото- кола Для таких параметров мы укажем соотве1ствующий заголовочный файл Приложения, использующие расширения Microsoft, нужно компоно- вать с библиотекой Mswsock lib
Параметры сокета
Функция getsockopt наиболее часто используется для получения информации о данном сокете lit getsockopt (
SOCKET s,
int level,
int optname,
char FAR* optval,
int FAR* optlen
)

IIJJUI
Первый параметр — s, он определяет сокет, с которым вы будете работать
Это должен быть действительный сокет для используемого протокола Ко- личество параметров зависит от протокола и типа сокета, хотя некоторые применимы ко всем типам сокетов Первый параметр связан со вторым —
level Параметр уровня SOL_SOCKET — универсальный, не обязательно харак- терный для данного протокола Мы говорим «не обязательно), потому что не все протоколы реализуют все параметры сокета на уровне SOLSOCKET На- пример, SOJBROADCAST переводит сокет в широковещательный режим, но не все поддерживаемые протоколы реализуют широковещательные сокеты
Фактически, нас интересует параметр optname
Имена параметров — постоянные значения, определенные в заголовоч- ных файлах Wmsock Большинство общих и независимых от протокола па- раметров (например, с уровнем SOL_SOCKET) определены в Winsock h и
Winsock2 h У каждого протокола есть свой заголовочный файл, где опреде- лены специфичные для него параметры И наконец, параметры optval и
optlen — переменные, возвращаемые со значением интересующего вас пара- метра (как правило, это целое)
Функция setsockopt позволяет задать параметры сокета на уровне сокета или протокола int setsockopt (
SOCKET s,
-i int level,
(
mt optname,
,1 const char FAR • optval,
,, int optlen rt Параметры те же, что и у getsockopt, кроме того, что вы передаете в функ- цию значения параметров optval n optlen, которые присваиваются определен- ным параметрам сокета Как и в getsockopt, optval, как правило, целое число
Типичная ошибка вызова getsockopt или setsockopt — попытка получить информацию о сокете, чей базовый протокол не поддерживает данную ха- рактеристику Например, сокет типа SOCKSTREAM не поддерживает широ- ковещание данных, поэтому попытка задать или получить значение парамет- ра SO BROADCAST вызовет ошибку WSAENOPROTOOPT
Уровень SOL_SOCKET
Рассмотрим параметры сокета, возвращающие информацию на основе ха- рактеристик самого сокета Данная информация не специфична для прото- кола сокета
Параметр SO_ACCEPTCONN
Этот параметр (тип optval — BOOL, версия Winsock 1+) можно только полу- чить Если возвращается TRUE, сокет находится в режиме прослушивания
Если сокет был переведен в режим прослушивания функцией listen, воз- вращается TRUE Сокеты типа SOCKDGRAM не поддерживают этот параметр

Г Л А В А 9 Параметры сокета и команды управления вводом-выводом 247
Параметр SO_BROADCAST
Этот параметр (тип optval — BOOL, версия Winsock 1+) можно и получить, и задать Если он равен TRUE, сокет сконфигурирован для отправки или при- ема широковещательных сообщений
Используйте setsockopt с параметром SOJBROADCAST для включения ши- роковещательных функций этого сокета Этот параметр допустим для всех сокетов, кроме типа SOCK_STREAM
Как уже упоминалось, широковещание — это возможность отправлять данные каждому компьютеру в локальной подсети Конечно, на каждом ком- пьютере должен быть запущен процесс, который прослушивает входящие широковещательные данные Недостаток широковещания в том, что если множество процессов одновременно отправляют широковещательные дан- ные, сеть может перенасытиться, из-за чего снизится ее быстродействие Для приема широковещательных сообщений, активизируйте соответствующий параметр и используйте одну из функций получения дейтаграмм, например
recvfrom или WSARecvfrom Также можно подключить сокет к широковеща- тельному адресу, вызвав connect или WSAConnect, а затем — recv или WSARecv
Для широковещания по UDP нужно указать номер порта для отправки дей- таграмм, аналогично, получатель должен запросить прием широковещатель- ных данных на том же порте Вот пример, иллюстрирующий, как отправить широковещательное сообщение по UDP
SOCKET s,
BOOL bBroadcast,
char *sMsg = This is a test ,
SOCKADDR.IN beast,
s = WSASocket(AF_INET, SOCK_DGRAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED),
bBroadcast = TRUE,
setsockopt(s, S0L_S0CKET, SO_BROADCAST, (char *)&bBroadcast,
sizeof(BOOL)),
beast sin_family = AF_INET,
beast sin_addr s_addr = inet_addr(INADDR_BROADCAST),
beast sin_port = htons(5150),
sendto(s, sMsg, strlen(sMsg), 0, (SOCKADDR *)&bcast, sizeof(bcast)),
В UDP предусмотрен специальный адрес, на который должны отправлять- ся широковещательные данные — 255255255255 Ему соответствует кон- станта INADDR_BROADCAST
AppleTalk также способен передавать широковещательные сообщения и также предусматривает специальный адрес для их приема В главе 6 мы упоми- нали, что адрес AppleTalk состоит из трех частей сеть, узел и сокет (пункт на- значения) Для широковещания пункт назначения равен ATADDRBROADCAST
(OxFF) — в результате дейтаграммы отправляются всем конечным точкам указанной сети
Обычно при отправке широковещательной дейтаграммы необходимо задать только парамет р SO_BROADCAST Для приема такой дейтаграммы про- слушивают только входящие дейтаграммы на заданном порте Впрочем, при

2 4 8 ЧАСТЬ II Интерфейс прикладного программирования Winsock использовании IPX в Windows 95, принимающий сокет должен задать пара- метр SO BROADCAST (см статью Q137914 в базе знаний по адресу http//
supportmicrosoft com/support/search, это ошибка Windows 95)
Параметр SO_CONNECT_TIME
Этот параметр (тип optval — int, версия Winsock 1+) можно только получить
Он задает длительность соединения на сокете в секундах
Параметр SO_CONNECT_TIME добавлен Microsoft Наиболее часто он ис- пользуется с функцией AcceptEx, которая требует, чтобы входящему клиентскому соединению был передан действительный описатель сокета
Параметр можно вызвать через клиентский описатель SOCKET, чтобы оп- ределить, было ли установлено соединение и сколько оно длилось Если со- кет в настоящее время не используется соединением, возвращается значе- ние OxFFFFFFFF
Параметр SO_DEBUG
Этот параметр (тип optval BOOL, версия Winsock 1+) можно и получить и задать Если он равен TRUE, вывод отладочной информации включен
Поставщики услуг Winsock поддерживают (но не требуют) вывод отла- дочной информации, если параметр SODEBUG задан приложением Способ представления отладочной информации зависит от реализации базового поставщика услуг Для включения вывода отладочной информации вызови- те функцию setsockopt с параметром SODEBUG и присвойте булевой пере- менной TRUE Вызов getsockopt с параметром SOJDEBUG возвращает TRUE или
FALSE, если отладка включена или выключена, соответственно К сожалению,
ни одна из платформ Win32 в настоящее время не реализует параметр SO_
DEBUG (см статью Q138965 в базе знаний) При задании этого параметра ошибки не выдаются базовый сетевой поставщик его просто игнорирует
Параметр SO_DONTUNGER
Этот параметр (тип optval — BOOL, версия Winsock 1+) можно и получить, и задать Если он равен TRUE, SOLLNGER отключен
Механизм плавного закрытия сокетного соединения реализован так, что если одна или обе стороны закрывают сокет, любые данные, ожидающие в очереди или передаваемые по сети, будут отправлены или приняты обеими сторонами Функция setsockopt и параметр SOJJNGER позволяют изменить это поведение и освободить через заданный период времени сокет и все его ресурсы Любые ожидающие или передаваемые данные, связанные с этим сокетом, отбрасываются и соединение сбрасывается (WSAECONNRESET) С
помощью параметра SOJDONTLINGER можно узнать, было ли задано время задержки Вызов getsockopt с параметром SOJDONTLINGER вернет TRUE или
FALSE, если время задержки было задано или нет, соответственно Вызов
setsockopt с параметром SOJDONTLINGER отключает задержку Сокеты типа
SOCKJDGRAM не поддерживают данный параметр t 1

Г Л А В А 9 Параметры сокета и команды управления вводом выводом 249
Параметр SOJONTROUTE
Этот параметр (тип optval — BOOL, версия Winsock 1+) можно и получить, и задать Если он равен TRUE сообщения отправляются прямо сетевому интер- фейсу в обход таблицы маршрутов
Параметр SODONTROUTE заставляет базовый сетевой стек игнорировать таблицу маршрутов и отправлять данные напрямую интерфейсу, с которым связан сокет Например, если вы создаете UDP-сокет и связываете его с ин- терфейсом А, а за!ем отправляете пакет, предназначенный компьютеру с интерфейсом В, пакет будет маршрутизирован так, чтобы передаваться сразу интерфейсу В Вызов setsockopt с параметром SODONTROUTE равным TRUE
предотвращает маршрутизацию, в итоге пакет направляется связанному ин- терфейсу Чюбы определить, включена ли маршрутизация (по умолчанию это так), вызовите функцию getsockopt
Этот параметр применим на платформах Win32, однако поставщик Mic- rosoft игнорирует такой запрос и всегда использует таблицу маршрутов, что- бы определить интерфейс для отправки исходящих данных
Параметр SO_ERROR
Этот параметр (тип optval — int, версия Winsock 1+) можно только получить
Он возвращает статус ошибки
Параметр SO ERROR возвращает и сбрасывает код ошибки для сокета,
который отличается от кода ошибки для потока — последний обрабатыва- ется функциями WSAGetLastEtror и WSASetLastError Успешный вызов не сбра- сывает код ошибки для данного сокета, возвращаемый в параметре SO_ER-
ROR — значение ошибки не всегда обновляется немедленно, поэтому есть ве- роятность что в этом параметре вернется 0 (то есть, что ошибки нет) Если не требуется знать индивидуальный код ошибки, лучше всегда использовать
WSAGetLastError
Параметр SO_EXCLUSIVEADDRUSE
Этот параметр (тип optval — BOOL, версия Winsock 2+) можно и получить, и задать Если он равен TRUE, локальный порт, с которым связан сокет, нельзя повюрно использовать в другом процессе
Этот параметр дополняет SO_REUSEADDR Параметр SO_EXCLUSLVEADD-
RUSE запрещает другим процессам использовать SOJREUSEADDR на локаль- ном адресе, который использует приложение Если два отдельных процесса связаны с одним локальным адресом (учитывая, что параметр SO_REUSEADDR
был задан ранее), не ясно, какой из двух сокетов будет получать уведомле- ния о входящих соединениях Это нежелательно, особенно если приложе- ние выполняет важную функцию Параметр SO_EXCLUSIVEADDRUSE блокиру- ет локальный адрес, с которым связан сокет В результате другой процесс не сможет использовать SO_REUSEADDR с тем же локальным адресом Этот па- раметр доступен только в Windows 2000, чтобы задать его значение, нужны полномочия администратора

I
Параметр SO_KEEPALIVE
Этот параметр (тип optval BOOL, версия Winsock 1+) можно и получить, и задать. Если он равен TRUE, сокет сконфигурирован для отправки в сеансе сообщений об активности соединения.
Для ТСР-сокета приложение может запросить, чтобы базовый поставщик услуг передавал пакеты сообщений об активности (keepalive packets) TCP- соединения, включив параметр SOKEEPALJVE. На платформах Win32 сооб- щения об активности соединения реализованы, согласно разделу 4.2.3.6 из
RFC 1122. После разрыва соединения любым вызовам, выполняющимся на сокете, возвращается ошибка WSAENETRESET Все последующие вызовы вер- нут ошибку WSAENOTCONN. Подробности реализации этого механизма см.
в RFC 1122. Важно, что сообщения об активности соединения выдаются не реже, чем через два часа — это значение задается в реестре. Изменение стан- дартного значения повлияет на все сообщения об активности соединения на всех TCP-соединениях в системе, что, как правило, нежелательно. Альтерна- тивное решение — реализовать собственный механизм сообщений об актив- ности соединения (см. также главу 7). Этот параметр не поддерживают со- кеты с типом SOCKJDGRAM.
Параметры сообщений об активности соединения регулируют парамет- ры реестра KeepAlivelnterval и KeepAliveTime (оба — типа REGDWORD), зада- ющие время в миллисекундах. Первый — это интервал между повторными передачами сообщения об активности, когда не получен отклик. Второй —
частота отправки пакетов для проверки доступности соединения. В Windows
95 и 98 эти параметры расположены в разделе:
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP
в Windows NT и 2000 в разделе:
\HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TCPIP\Parameters
В Windows 2000 есть новая команда управления вводом-выводом — SIO_
KEEPALIVE_VALS (описана далее), позволяющая изменить значение и интер- вал сообщений об активности отдельно для каждого сокета, а не в масшта- бе всей системы.
Параметр SOJ.INGER
Этот параметр (тип optval struct linger, версия Winsock 1+) можно и полу- чить, и задать. С его помощью определяют текущие значения задержки.
SOJUNGER задает действие, предпринимаемое после выполнения функ- ции closesocket, если в очереди на сокете есть еще не отправленные данные.
Вызов getsockopt с этим параметром возвращает текущие значения задерж- ки в структуре linger.
struct linger {
u_short l_onoff;
u_short l_linger;

Г Л А В А 9 Параметры сокета и команды управления вводом-выводом 251
Ненулевое значение Ijynqff означает, что задержка включена, а в поле
IJinger хранится тайм-аут в секундах. По прошествии этого времени любые ожидающие отправки или приема данные отбрасываются, и соединение с партнером разрывается. Напротив, вы можете вызвать setsockopt, чтобы включить задержку и назначить тайм-аут. Для этого задайте необходимые значения в переменной с типом struct linger-, поле l_onoff структуры не дол- жно быть равно 0. Для отключения задержки вызовите setsockopt с парамет- ром SOJJNGER, присвоив 0 полю l_onqff структуры linger, или setsockopt с па- раметром SOJDONTLINGER и передав TRUE в параметре optval. Сокеты типа
SOCKJDGRAM не поддерживают параметр SODONTIJNGER.
Настройка задержки напрямую влияет на поведение соединения при вы- зове closesocket (табл. 9-1).
Табл. 9-1. Параметры задержки
Параметр Интервал Тип закрытия Ожидать ли закрытия
SOJDONTLINGER Неприменим Плавное Нет
SOJJNGER 0 Резкое Нет
SOJJNGER Ненулевой Плавное Да
Если параметр SOJJNGER задан с нулевым тайм-аутом (то есть поле l_onoff
структуры linger не равно 0, а поле IJinger равно 0), вызов closesocket не бло- кируется, даже если данные в очереди еще не были отправлены или подтвер- ждены. Это называется резким или преждевременным закрытием сокета,
поскольку виртуальный канал связи сбрасывается немедленно, и любые не отправленные данные теряются. Любой принимающий вызов на противопо- ложной стороне канала вернет ошибку WSAECONNRESET.
Если SOJJNGER задан с ненулевым тайм-аутом на блокирующем сокете,
вызов closesocket блокируется на этом сокете, пока оставшиеся данные не будут отправлены или не истечет тайм-аут. Это называется плавным завер- шением соединения. Если таймаут истечет до отправки всех данных, реали- зация сокетов в Windows завершит соединение до возврата из closesocket.
Параметр SO_MAX_MSG_SIZE
Этот параметр (тип optval unsigned int, версия Winsock 2+) предназначен только для чтения и показывает максимальный размер исходящего сообще- ния для типов сокетов, ориентированных на обмен сообщениями, согласно реализации конкретного поставщика службы. Он не применим к поточным сокетам. Средств определения максимального размера входящего сообще- ния не предусмотрено.
Параметр SOJDOBINLINE
Этот параметр (тип optval BOOL, версия Winsock 1+) можно и получить, и задать. Если он равен TRUE, внешние данные возвращаются в обычном по- токе данных.
По умолчанию срочные данные (out-of-band, OOB) не передаются в основ- ном потоке, то есть функция приема (с заданным соответствующим флагом

2 5 2 ЧАСТЬ II Интерфейс прикладного программирования Wmsock
MSGOOB) возвращает ООВ данные за один вызов Если это г параметр задан,
ООВ-данные появляются внутри потока данных, возвращаемого вызовом при- ема, и чтобы определить, какой бай г относит ся к ООВ-данпым нужно вызвать
toctlsocket с параме гром SIOCA1MARK Сокет ы т ипа SOCKDGRAA1 не поддержи- вают этот параметр, кроме того, он неустойчиво работает во всех текущих реализациях Win32 Подробнее об ООВ-данных — в главе 7
Параметр SO_PROTOCOL_INFO
Этот параметр (тип optval WSAPROTOCOLJNFO, версия Winsock 2+) мож- но только получить Он определяет характеристики протокола, связанного с сокетом
Это еще один параметр только для чтения, который заполняет структуру
WSAPROГОСО1 INFO характеристиками протокола, сопоставленного сокегу
Описание структуры WSAPROTOCOLINbO см в главе 6
Параметр SO_RCVBUF
Этот параметр (гип optval — int версия Winsock 1+) можно и получить, и задать Он определяет размер буфера приема данных, связанного с данным сокетом Каждому созданному сокету назначаются буферы отправки и при- ема В ответ на запрос о размере буфера приема в вызове setsockopt не будет выдана ошибка, даже если реализация не в состоянии предос гавить буфер указанного размера Поэтому чтобы узнать, какой буфер фактически выде- лен, вызовите getsockopt Задавать и получать размер буфера приема позво- ляют все платформы Win32, кроме Windows СЕ, где можно лишь узнать раз- мер этого буфера
Вам может потребоваться изменить размер буфера, чтобы приспособить его к своему приложению Например, в коде, принимающем UDP-дейтаграм- мы, размер буфера приема, как правило, должен быть кратен размеру дей- таграммы
При перекрытом вводе-выводе нулевой размер буфера может увеличить производительность, например, если требуется дополнительно копировать содержимое памяти для переноса данных из системного буфера в пользо- вательский В отсутствие промежуточного буфера данные копируются сра- зу в пользовательский Впрочем, такой подход эффективен, только если нуж- но обрабатывать множество ожидающих вызовов приема При асинхронной обработке единичных операций приема производительность снизится, по- скольку локальная система не сможет принимать входящие данные, пока у вас не будет для них готового буфера Подробнее об этом — в главе 8
Параметр SO_REUSEADDR
Этот параметр (тип opti al — BOOL версия Winsock 1+) можно и получить, и задать Если он равен TRUE, вы вправе связать сокет только с адресом, уже используемым дру1 им сокетом, или с адресом в состоянии TIME_WAIT
По умолчанию сокет не может быть связан с уже используемым локаль- ным адресом, однако иногда необходимо многократно использовать адрес

Г Л А В А 9 Параметры сокета и команды управления вводом выводом 253
таким образом Мы уже говорили, что каждое соединение однозначно иден- тифицируется комбинацией его локальною и удаленного адресов Если ад- рес, с которым вы соединяетесь, хоть чем-то уникален (например, у него другой номер порта TCP/IP), привязка к нему разрешена
Единственное исключение — слушающие сокеты Два разных сокета нельзя связать с одним локальным интерфейсом (и портом — в случае TCP/IP) для ожидания входящих соединений Когда два сокета активно прослушивают на одном порте, невозможно предсказать, какой именно из них получит уве- домление о входящем соединении Параметр SO_REUSEADDR наиболее поле- зен в TCP, если сервер завершил работу (в том числе преждевременно), ос- тавив локальный адрес и порт в состоянии TIME_WAIT Тогда другие сокеты будет невозможно связать с <зависшим» портом Если задать эгот параметр,
сервер сможет прослушивать на том же локальном интерфейсе и порте пос- ле перезагрузки
Параметр SOJSNDBUF
Этот параметр (тип optval — BOOL, версия Winsock 1+) можно и получить, и задать Он сравнительно прост и определяет размер буфера отправки дан- ных, связанного с конкретным сокетом Значение TRUE (ненулевое) означа- ет, что сокет настроен для отправки широковещательных сообщений Каж- дому созданному сокету назначаются буферы отправки и приема В ответ на запрос о размере буфера приема в вызове setsockopt не будет выдана ошиб- ка, даже если реализация не в состоянии предоставить буфер указанного размера Поэтому чтобы узнать какой буфер фактически выделен, вызовите
getsockopt Задавать и получать размер буфера отправки позволяют все т а т - формы Win32, кроме Windows СЕ, где его можно лишь узнать
Как и SOJZCVBUF, параметр SO_SNDBUF можно использовать, чтобы задать нулевой размер буфера отправки — тогда по завершении блокирующего вызова отправки можно быть уверенным, что данные переданы в сеть Кро- ме того, как и в операции приема без буфера, не требуется дополнительно копировать содержимое памяти в системные буферы Однако при этом вы теряете преимущества конвейерной работы буферов стека, когда их размер не равен 0 Другими словами, если программа циклически отправляет дан- ные, локальный сетевой стек копирует эти данные в системный буфер, ко- торый фактически отправляет их по мере возможности (зависит от исполь- зуемой модели ввода-вывода)
Если же логика вашего приложения иная, отключение буферов отправки сэкономит вам несколько машинных команд на копировании памяти Под- робнее об этом — в главе 8
Параметр SOJTYPE
Этот параметр SOJTYPE (тип optval — mt, версия Winsock 1+) можно только получить Он доступен только для чтения и просто возвращает тип данного сокета SOCKJDGRAM, SOCKJTREAM, SOCKJEQPACKET, SOCK_RDM и SOCKJWW
J. *»«"*-

2 5 4 ЧАСТЬ II Интерфейс прикладного программирования Winsock
Параметр SO_SNDTIMEO
Этот параметр (тип opWal — int, версия Winsock 1+) можно и задать, и полу- чить Он определяет тайм-аут па блокирующем сокете, учитываемый при вызовах функций отправки данных Значение тайм-аута в миллисекундах указывает длительность блокирования при отправке данных Если необхо- димо использовать SO_SNDTIMEO вместе с функцией WSASocket (для созда- ния сокета), укажите WSA_FLAG OVERLAPPED в составе параметра divFlags
функции WSASocket Последующие вызовы любой Winsock-функции отправ- ки (send, sendto, WSASend, WSASendTo и т п ) блокируют только на заданную величину времени Если операция отправки не завершается за это время,
вызов вернет ошибку 10060 (WSAETIMEDOUT)
Для увеличения производительности этот параметр отключен в Windows
СЕ 2 1- он просто игнорируется, ошибка не выдается В предыдущих верси- ях Windows СЕ параметр работает
Параметр SO_RCVTIMEO
Этот параметр (тип optval int, версия Winsock 1+) можно и задать, и полу- чить Он назначает тайм-аут на блокирующем сокете, учитываемый при вы- зовах функций приема данных Значение таймаута в миллисекундах опре- деляет длительность блокирования при приеме данных Если необходимо использовать SOJSNDTLMEO вместе с функцией WSASocket (для создания со- кета), укажите WSA_FLAG OVERLAPPED в составе параметра divFlags функции
WSASocket Последующие вызовы любой Winsock-функции приема (recv, recvf-
rom, WSARecv, WSARecvFrom и т п ) блокируют только на заданную величину времени. Если операция отправки не завершается за это время, вызов вер- нет ошибку 10060 (WSAETIMEDOUT)
Для увеличения производительности этот параметр отключен в Windows
СЕ 2 1 он просто игнорируется, ошибка не выдается В предыдущих верси- ях Windows СЕ параметр работает.
Параметр SO_UPDATE_ACCEPT_CONTEXT
Этот параметр (тип optval — SOCKET, версия Winsock 1+) можно и задать, и получить. Он определяет таймаут приема данных на сокете (в миллисекун- дах) Это расширение Microsoft чаще всего используется вместе с функцией
AcceptEx Уникальная особенность данной функции — она входит в специ- фикацию Winsock 1 и позволяет использовать перекрытый ввод-вывод для обработки вызова приема Функции AcceptEx в качестве параметра переда- ется прослушивающий сокет, а также описатель сокета, который должен быть принят клиентом.
С помощью параметра SOJJPDATE ACCEPT_CONTEXTклиентскому сокету назначают характеристики прослушивающего сокета Этот параметр обязате- лен для прослушивающего сокета QoS-приложения — в функции setsockopt ис- пользуйте прослушивающий сокет как параметр SOCKET, а описатель прини- мающего сокета (например, клиента) — как параметр optval Параметр SOJJP-
DATE ACCEPT CONTEXTприменяется лишь в Windows NT и 2000

Г Л А В А 9 Параметры сокета и команды управления вводом-выводом 255
Уровень параметров SOL_APPLETALK
Описанные в этом разделе параметры специфичны для протокола Apple-
Talk и могут использоваться только с сокетами, созданными функцией
socket или WSASOCKETc флагом AF_APPLETALK. Большинство этих парамет- ров связано с заданием либо с получением имен AppleTalk Подробнее о семействе адресов AppleTalk — в главе б У некоторых параметров сокета
AppleTalk (типа SO_DEREGISTER_NAME) несколько имен, все они взаимоза- меняемы.
Параметр SO_CONFIRM_NAME
Этот параметр (тип optval — WSH_NBP_TUPLE, версия Winsock 1) можно только получить. Он подтверждает, что данное имя AppleTalk связано с ука- занным адресом Для проверки имени по этому адресу отправляется запрос поиска по протоколу Name Binding Protocol (NBP) Если он возвращает ошиб- ку WSAEADDRNOTAVA1L, значит имя больше не связано с адресом
Параметры SO_DEREGISTER_NAME и SO_REMOVE_NAME
Этот параметр (тип optval — WSHREGISTER_NAME, версия Winsock 1) мож- но и получить, и задать Они отменяют регистрацию имени в сети Если на данный момент имени в сети не существует, вызов выполнится успешно.
Подробнее о структуре WSH_REGISTER_NAME, которая, по сути, просто дру- гое название WSH_NBP_NAME — в главе 6.
Параметры SO_LOOKUP_MYZONE и SO_GETMYZONE
Эти параметры (тип optval — char', версия Winsock 1) можно только задать.
Они возвращают стандартную зону сети Параметр optval для getsockopt
строка, длиной минимум 33 символа. Как вы знаете, максимальная длина
NBP-имени — MAX_ENTI1Y_LEN, который равен 32 Дополнительный символ необходим для нулевого терминатора строки
Параметр SO_LOOKUP_NAME
Этот параметр (тип optval WSH_LOOKUP_NAME, версия Winsock 1) можно только задать. Его применяют для поиска в сети указанного имени NBP, он возвращает соответствующие комбинации имен и информации NBP (напри- мер, когда клиент хочет соединиться с сервером) Перед установлением свя- зи нужно разрешить в адрес AppleTalk стандартное (well-known) текстовое имя. Пример кода для поиска имени AppleTalk — в главе 6.
Учтите, что после успешного возвращения структуры WSH_NBP_TUPLE
располагаются в буфере вслед за информацией WSH LOOKUP_NAME Поэто- му нужно указать в вызове getsockopt буфер достаточного размера, чтобы туда поместились все возвращенные сведения. WSH_LOOKUP_NAME — в начале бу- фера и ряды структур WSH_NBP_TUPLE — в конце (рис. 9-1)-
Рис. 9-1. Буфер SOJLOOKUPJNAME

2 5 6 ЧАСТЬ II Интерфейс прикладного программирования Winsock
Параметры SO_LOOKUP_ZONES и SO_GETZONELIST
Этот параметр (тип optval — WSH_LOOKUP_ZONES, версия Winsock 1) мож- но только получить Он возвращает имена зон возвращений из списка зон в
Интернете Нужен достаточно вместительный буфер, чтобы разместить в его f
начале структуру WSH LOOKUPJZONES. Если возвращение успешно, про- странство после структуры WSH_LOOKUP ZONES содержит список имен зон/
с нулевым символом в конце Приведенный далее код иллюстрирует испопщ
зование параметра SO LOOKUPJZ.ONES I
PWSH_LOOKUP_NAHE atlookup,
PWSH_LOOKUP_ZONES zonelookup;
char cLookupBuffer[4096],
•pTupleBuffer = NULL;
atlookup = (PWSH_LOOKUP_NAME)cLookupBuffer;
zonelookup = (PWSH_LOOKUP_ZONES)cLookupBuffer;
ret = getsockopt(s, SOL_APPLETALK, SO_LOOKUP_ZONES, (char *)atlookup,
&dwSize);
pTupleBuffer = (char *)cLookupBuffer + sizeof(WSH_LOOKUP_ZONES);
for(i = 0; l < zonelookup->NoZones;
prmtf("X3d. 'Xs'\n", 1 + 1, pTupleBuffer);
while (*pTupleBuffer++);
Параметры SO_LOOKUP_ZONES_ON_ADAPTER и SO_GETLOCALZONES
Эти параметры (тип optval — WSH_LOOKUP_ZONES, версия Winsock 1) мож- но только получить. Они возвращают список имен зон, известных адаптеру с указанным именем Это похоже на работу SO_LOOKUP_ZONES, за одним ис- ключением при использовании SO_LOOKUP_ZONES_ON_ADAPTER и SO_ GET-
LOCALZONES вы можете указать имя адаптера и получить список зон для ло- кальной сети, к которой тот подключен Также необходим вместительный буфер, в начале которого разместится структура WSH_LOOKUP ZONES Воз- вращенный список имен зон, разделенных нулевым символом, начинается после структуры WSH_LOOKUP_ZONES Имя адаптера должно быть строкой
UNICODE (WCHAR).
Параметры SO_LOOKUP_NETDEF_ON_ADAPTER и SO_GETNET1NFO
Эти параметры (тип optval WSH_LOOKUP NETDEF ON ADAPTER, версия
Winsock 1) можно только задать Они возвращают диапазоны сетевых номе- ров и ANSI-сгроку с нулевым символом в конце, содержащую стандартную зону для сети на указанном адаптере Сведения об адаптере передаются в строке UNICODE (WCHAR) вслед за структурой и перезаписываются инфор- мацией о стандартной зоне по возвращении Если сеть не фрагментирова-
на (seeded), возвращается сетевой диапазон 1-OxFFFE, а в ANSI-строке с ну- левым символом в конце содержится стандартная зона — «*•>

Г Л А В А 9 Параметры сокета и команды управления вводом-выводом 257
Параметр SO_PAP_GET_SERVER_STATUS
Этот параметр (тип optval WSH_PAP GET SERVER_STATUS, версия Winsock 1)
можно только получить Он возвращает статус РАР от заданного сервера — ото- бражает состояние протокола Printer Access Protocol (PAP), зарегистрированно- го по адресу, указанному в ServerAddr (обычно известен по поиску NBP) Четы- ре зарезервированных байта соответствуют четырем зарезервированным бай- там в пакете состояния РАР (в сетевой порядке байт) Строка состояния РАР не стандартизована и задается параметром SO_PAP_SET_SERVER_STATUS. Структу- ра WSH_PAP_GET_SERVER__STATUS определена так.
#define MAX_PAP_STATUS_SIZE 255
#define PAP_UNUSED_STATUS_BYTES 4
typedef struct _WSH_PAP_GET_SERVER_STATUS
{
SOCKADDR_AT ServerAddr;
UCHAR Rese rved[PAP_UNUSED_STATUS_BYTES];
UCHAR ServerStatus[MAX_PAP_STATUS_SIZE + 1];
} WSH_PAP_GET_SERVER_STATUS, *PWSH_PAP_GET_SERVER_STATUS;
Приведем краткий пример опроса состояния РАР. Длина строки состоя- ния записана в первом байте поля ServerStatus
WSH_PAP_GET_SERVER_STATUS status;
mt nSize = sizeof(status);
status.ServerAddr.sat_family = AF_APPLETALK,
ret = getsockopt(s, SOL_APPLETALK, SO_PAP_GET_SERVER_STATUS,
(char *)&status, &nSize);
Параметр SO_PAP_PRME_READ
Этот параметр (тип optval char [], версия Winsock 1) можно только задать
Его вызов предваряет чтение по соединению РАР На сокете, описывающем подключение РАР, он позволяет удаленному клиенту отправить данные, даже если локальное приложение не вызвало recv или WSARECVEX Задав этот па- раметр, приложение может блокировать вызов select, а затем считать данные
Параметр optval для этого вызова — буфер, принимающий данные, длиной минимум MIN_PAP_READJ3UF_SIZE (4096) байт Он позволяет работать с не- блокирующими сокетами по протоколу PAR Заметьте, что для каждого буфе- ра, который вы хотите считать, необходимо вызвать setsockopt с параметром
SO_PAP_PRIME_READ
Параметр SO_PAP_SET_SERVER_STATUS
Этот параметр (тип optval — char [], версия Winsock 1) можно только задать
°н определяет состояние РАР, отправляемое в ответ на соответствующий запрос другого клиента При этом клиенту будет возвращаться содержимое

2 5 8 ЧАСТЬ II Интерфейс прикладного программирования Winsock указанного буфера, объем которого — не более 255 байт. Если задать пустой буфер состояния, его предыдущее содержимое будет стерто.
Параметр SO_REGISTER_NAME
Этот параметр (тип optval — WSH REGISTER JVMIE, версия Winsock 1) мож- но только задать. Он используется для регистрации указанного имени в сети
AppleTalk. Если это имя уже существует в сети, выдается ошибка WSAEAD*
DRINUSE. Подробнее о структуре WSH_REGISTER_NAME — в главе 6.
Уровень параметров SOLJRLMP
Уровень SOLJRLMP связан с протоколом IrDA (семейство адресов AFJRDA).
При использовании описанных далее параметров учтите, что инфракрасные
(ИК) сокеты реализованы на всех платформах по-разному. Поскольку Win- dows СЕ первая стала поддерживать IR, в этой ОС доступны не все парамет- ры, представленные позже в Windows 98 и Windows 2000. В этом разделе описание каждого параметра мы сопровождаем перечнем поддерживающих его платформ.
Параметр IRLMP_9WIRE_MODE
Этот параметр (тип optval BOOL, версия Winsock 1+) можно и получить, и задать. Он определяет параметры IP в рамках заголовка IP. Это еще один ред- ко используемый параметр, необходимый для связи с Windows 98 по IrCOMM,
уровень которого ниже, чем тот, на котором обычно работает IrSock. В девя- типроводном режиме каждый пакет TinyTP или IrLMP содержит дополнитель- ный однобайтовый заголовок IrCOMM.
Чтобы добиться этого через интерфейс сокета, необходимо сначала по- лучить максимальный размер PDU для IrLMP-пакета с параметром 1RLMP_
SEND_PDU_LEN. Затем перед началом или приемом соединения сокет пере- водится функцией setsockopt в девятипроводной режим. Она дает указание стеку добавлять однобайтовый заголовок IrCOMM (всегда равный 0) к каж- дому отсылаемому кадру Поэтому размер каждого отправляемого send бло- ка данных должен быть меньше максимальной длины PDU, дабы оставить ме- сто для добавленного байта IrCOMM.
Протокол IrCOMM не рассматривается в этой книге. Параметр доступен на Windows 98 и Windows 2000.
Параметр IRLMP^ENUMDEVICES
Этот параметр (тип optval DEVICELIST, версия Winsock 1+), можно только получить. Инфракрасные устройства связи по своей природе мобильны и могут входить и выходить из области видимости. Этот параметр «опраши- вает» ИК-устройства в области видимости, нумеруя их, и возвращает список их идентификаторов.
Структуры DEVICELIST на разных платформах, поддерживающих IrSock,
отличаются друг от друга, поскольку новые платформы обладают расширен- ной функциональностью. Изначально поддержка IrSock была реализована в
I

Г Л А В А 9 Параметры сокета и команды управления вводом-выводом 259
Windows СЕ, а в Windows 98 и Windows 2000 появилась позже Определение структуры DEVICELJST для Windows 98 и Windows 2000 выглядит так:
typedef struct _WINDOWS_DEVICELIST
{
ULONG numDevice;
WINDOWS_IRDA_DEVICE_INFO Device[1];
} WINDOWS_DEVICELIST, *PWINDOWS_DEVICELIST, FAR *LPWINOOWS_DEVICELIST;
typedef struct _WINDOWS_IRDA_DEVICE_INFO
{
u_char irdaDeviceID[4];
°' char irdaDeviceName[22];
** u_char irdaDeviceHintsi;
* u_char irdaDeviceHints2;
u_char irdaCharSet;
} WINDOWS_IRDA_DEVICE_INF0, *PWINDOWS_IRDA_DEVICE_INFO,
FAR *LPWINDOWS_IRDA_DEVICE_INFO;
В Windows СЕ структура DEVICELIST определена таю typedef struct _WCE_DEVICELIST
{
ULONG numDevice;
WCE_IRDA_DEVICE_INFO Device[1];
} WCE_DEVICELIST, *PWCE_DEVICELIST;
typedef struct _WCE_IRDA_DEVICE_INFO
{
u_char irdaDeviceI0[4];
char irdaDeviceName[22];
u_char Reserved[2];
> WCE_IRDA_DEVICE_INFO, »PWCE_IRDA_DEVICE_INFO;
Как видите, структура информации устройства тоже иная: WCE_IRDA_DE-
VICEJNFO — для Windows СЕ и WINDOWSJRDAJDEVICEJNFO — для Windows
98 и Windows 2000. Каждая из этих структур содержит поле irdaDevicelD —
четырехбайтный тег, однозначно идентифицирующий устройство. Это поле необходимо для заполнения структуры SOCKADDRJRDA, которую использу- ют для соединения с конкретным устройством, а также для получения запи- си службы доступа к информации (Information Access Service, IAS) с парамет- рами IRLMPJASJET и IRLMP_IAS_QUERY.
При перечислении ИК-устройств в ходе вызова getsockopt необходимо,
чтобы параметр optval был структурой DEVICELIST. Единственное требова- ние — сначала присвоить 0 полю numDevice. Вызов getsockopt не возвраща- ет ошибку, если ИК-устройства не обнаружены. Необходимо проверить зна- чение поля numDevice: если оно больше 0, то было найдено одно или не- сколько устройств. Поле Device возвращается с числом структур, равным значению в поле numDevice.
t i l to ЛАМ

260
ЧАСТЬ II Интерфейс прикладного программирования Winsock
Параметр IRLMP_EXCLUSIVE_MODE
Этот параметр (тип optval —BOOL, версия Winsock 1+) можно и получить, и задать Если он равен TRUE, соке гное соединение работает в монопольном режиме Параметр обычно не употребляется пользовательскими приложени- ями, поскольку обходит уровень TinyTP в стеке IrDA и связывается напрямую с IrLMP Если вы действительно заинтересованы в его использовании, озна- комьтесь со спецификацией IrDA по адресу http //www irdaorg Доступен BJ
Windows СЕ и Windows 2000 ,
f
Параметр IRLMPJASJQUERY
Этот параметр (тип optval IAS_QUERY, версия Winsock 1+) можно только получить Он опрашивает IAS относительно атрибутов указанной службы и класса Параметр дополняет IRLMPJASJSET и находит информацию об име- ни класса и его службе
Перед вызовом getsockopt сначала заполните поле irdaDevicelD для ссыл- ки на опрашиваемое устройство Введите в поле irdaAttnbName строку свой- ства, по которой хотите отыскать его значение Как правило, опрашивается номер LSAP-SEL, его строка свойства — IrDA IrLMP LsapSel Затем задайте полю irdaClassName имя службы, которой соответствует данная строка свой- ства После заполнения этих полей вызовите getsockopt В случае успеха
irdaAttnbType указывает, из какого поля объединения следует получать ин- формацию Для декодирования этой записи используйте идентификато- ры из табл 9-2 (вы найдете ее чуть далее в этой главе) Типичная ошибка
WSASERVICE_NOT_FOUND возвращается, если данная служба не обнаружена на указанном устройстве Параметр доступен в Windows СЕ/98/2000
Параметр IRLMPJASJSET
Этот параметр (тип optval IAS_QUERY, версия Winsock I +) можно только задать Служба IAS — это управляемый механизм динамической регистрации
IRLMPJASJSET позволяет задать один атрибут для одного класса в локальной
IAS Как и в случае с IRLMP_ENUMDEVICES, предусмотрены разные структуры для Windows СЕ/98/2000 Структуры для Windows 98 и Windows 2000 таковы typedef struct _WINDOWS_IAS_QUERY
u_char char char u_long union
LONG
s t r u c t irdaDeviceID[4],
irdaClassName[IAS_MAX_CLASSNAME];
irdaAttnbName[IAS_MAX_AnRIBNAME]
lrdaAttnbType,
i r d a A t t n b l n t ,
u_long Len,
u_char OctetSeq[IAS_MAX_OCTET_STRING];
} irdaAttribOctetSeq,

1   ...   19   20   21   22   23   24   25   26   ...   50


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