Программирование в сетях Windows
.pdf2 48 |
ЧАСТЬ 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, однако поставщик Microsoft игнорирует такой запрос и всегда использует таблицу маршрутов, чтобы определить интерфейс для отправки исходящих данных
ПараметрSO_ERROR
Этот параметр (тип optval — int, версия Winsock 1+) можно только получить Он возвращает статус ошибки
Параметр SO ERROR возвращает и сбрасывает код ошибки для сокета, который отличается от кода ошибки для потока — последний обрабатывается функциями WSAGetLastEtror и WSASetLastError Успешный вызов не сбрасывает код ошибки для данного сокета, возвращаемый в параметре SO_ERROR — значение ошибки не всегда обновляется немедленно, поэтому есть вероятность что в этом параметре вернется 0 (то есть, что ошибки нет) Если не требуется знать индивидуальный код ошибки, лучше всегда использовать
WSAGetLastError
ПараметрSO_EXCLUSIVEADDRUSE
Этот параметр (тип optval — BOOL, версия Winsock 2+) можно и получить, и задать Если он равен TRUE, локальный порт, с которым связан сокет, нельзя повюрно использовать в другом процессе
Этот параметр дополняет SO_REUSEADDR Параметр SO_EXCLUSLVEADDRUSE запрещает другим процессам использовать SOJREUSEADDR на локальном адресе, который использует приложение Если два отдельных процесса связаны с одним локальным адресом (учитывая, что параметр SO_REUSEADDR был задан ранее), не ясно, какой из двух сокетов будет получать уведомления о входящих соединениях Это нежелательно, особенно если приложение выполняет важную функцию Параметр SO_EXCLUSIVEADDRUSE блокирует локальный адрес, с которым связан сокет В результате другой процесс не сможет использовать SO_REUSEADDR с тем же локальным адресом Этот параметр доступен только в Windows 2000, чтобы задать его значение, нужны полномочия администратора
ПараметрSO_KEEPALIVE
IЭтот параметр (тип 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) не передаются в основном потоке, то есть функция приема (с заданным соответствующим флагом
252 ЧАСТЬ 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
По умолчанию сокет не может быть связан с уже используемым локальным адресом, однако иногда необходимо многократно использовать адрес
254 |
ЧАСТЬ 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, recvfrom, 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 Параметр SOJJPDATE ACCEPT CONTEXTприменяется лишь в Windows NT и 2000
2 56 ЧАСТЬ 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_ GETLOCALZONES вы можете указать имя адаптера и получить список зон для локальной сети, к которой тот подключен Также необходим вместительный буфер, в начале которого разместится структура 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) можно только задать °н определяет состояние РАР, отправляемое в ответ на соответствующий запрос другого клиента При этом клиенту будет возвращаться содержимое