
Программирование_распределенных_систем / PRS_Lec
.pdfИнформация о протоколе
int WSAEnumProtocols(
_In_ LPINT lpiProtocols,
_Out_ LPWSAPROTOCOL_INFO lpProtocolBuffer, _Inout_ LPDWORD lpdwBufferLength
);
Если lpiProtocols== NULL , то выводится информация о всех протоколах
В системе может быть установлено несколько провайдеров для одного протокола.Из-за этого количество использованных
элементов в массиве lpProtocolBuffer может превышать количество
протоколов, определяемых параметром lpiProtocols. WSAPROTOCOL_INFO — содержит всю информацию о протоколе
|
WSASocket |
SOCKET WSASocket( |
|
_In_ |
int af, |
_In_ |
int type, |
_In_ |
int protocol, |
_In_ |
LPWSAPROTOCOL_INFO lpProtocolInfo, |
_In_ |
GROUP g, |
_In_ |
DWORD dwFlags |
); |
|
Если указатель lpProtocolInfo равен NULL, функция создаёт
сокет на основании первых трёх параметров так же, как это
делает функция Socket.
Иначе: первые три параметра должны быть равны константе From_Protocol_Info (-1).
Вызов функции Socket эквивалентен вызову функции WSASocket
с флагом WSA_Flag_Overlapped, который показывает, что данный
сокет можно использовать для перекрытого ввода-вывода
WSAConnect
int WSAConnect(
_In_ |
SOCKET s, |
_In_ |
const struct sockaddr *name, |
_In_ |
int namelen, |
_In_ |
LPWSABUF lpCallerData, |
_Out_ |
LPWSABUF lpCalleeData, |
_In_ |
LPQOS lpSQOS, |
_In_ |
LPQOS lpGQOS |
); |
|
Протоколы стека TCP/IP не поддерживают передачу данных при
соединении, поэтому при использовании TCP и UDP lpCallerData и lpCalleeData должны быть равны NULL.
Первые ТРИ параметра == как в функции Connect
|
WSAAccept |
SOCKET WSAAccept( |
|
_In_ |
SOCKET s, |
_Out_ |
struct sockaddr *addr, |
_Inout_ LPINT addrlen, |
|
_In_ |
LPCONDITIONPROC lpfnCondition, |
_In_ |
DWORD_PTR dwCallbackData |
);
Для фильтра подключающихся клиентов приходилось
разрывать соединение после подключения
lpfnCondition является указателем на функцию обратного вызова. Эта функция объявляется и реализуется программой. WSAAccept вызывает её внутри себя и в зависимости от её результата принимает или отклоняет соединение.
Функция должна вернуть CF_Accept (0), если соединение
принимается, CF_Reject (1), если оно отклоняется, и CF_Defer (2), если решение о разрешении или запрете соединения
откладывается.
Асинхронный режим, основанный на сообщениях
Асинхронный режим с уведомлением через сообщения
устанавливается функцией WSAAsyncSelect:
int WSAAsyncSelect( _In_ SOCKET s,
_In_ HWND hWnd,
_In_ unsigned int wMsg, _In_ long lEvent
);
S определяет сокет, для которого устанавливается асинхронный режим
работы.
hWnd - дескриптор окна, которому будут приходить сообщения, wMsg — сообщение
lEvent задаёт события, которые вызывают отправку сообщения.
Например:
FD_Read Сокет готов к чтению
FD_Accept в очереди сокета есть подключения (применимо только для сокетов, находящихся в режиме ожидания подключения)…
Каждый последующий вызов WSAAsyncSelect для одного и того же сокета отменяет предыдущий вызов.
Функция WSAAsyncSelect переводит сокет в неблокирующий режим
При получении сообщения его параметр wParam содержит дескриптор сокета, на котором произошло событие. Младшее слово lParam содержит произошедшее событие (одну из констант FD_XXX), а старшее слово - код ошибки.
Как только соответствующее сообщение помещается в очередь окна, дальнейшая генерация таких сообщений для этого сокета блокируется
Если после вызова Recv в буфере асинхронного сокета остались данные, в очередь окна снова помещается это же сообщение
Возможны ложные срабатывания
Асинхронный режим, основанный на событиях
Каждое событие может находится в сброшенном или взведённом состоянии
Сокетные события отличаются от стандартных системных событий прежде всего тем, что они могут быть связаны с событиями FD_XXX, происходящими на сокете, и взводиться при наступлении этих событий
Создание события: WSAEVENT WSACreateEvent(void); (в сброшенном состоянии)
Операции над событием:
BOOL WSASetEvent(WSAEVENT hEvent); BOOL WSAResetEvent(WSAEVENT hEvent);
Удаление события: BOOL WSACloseEvent(WSAEVENT hEvent);
…
Ожидание событий:
DWORD WSAWaitForMultipleEvents(
_In_ |
DWORD cEvents, |
_In_ |
const WSAEVENT *lphEvents, |
_In_ |
BOOL fWaitAll, |
_In_ |
DWORD dwTimeout, |
);_In_ |
BOOL fAlertable |
Дескрипторы событий, взведения которых ожидает нить, должны храниться в массиве, размер которого передаётся через параметр cEvents, а указатель - через параметр lphEvents
Если fWaitAll== TRUE , ожидание ВСЕХ событий
Результат, возвращаемый функцией, позволяет определить, по каким причинам закончилось ожидание:
Если ожидалось взведение всех событий, то WSA_Wait_Event_0 Если ожидалось взведение хотя бы одного из событий, возвращается
WSA_Wait_Event_0 + Index
Если произошла какая-либо ошибка, функция возвращает WSA_Wait_Failed
WSAEventSelect
int WSAEventSelect(
_In_ |
SOCKET s, |
_In_ |
WSAEVENT hEventObject, |
);_In_ |
long lNetworkEvents |
События FD_XXX привязываются не к оконным сообщениям, а к сокетным событиям
Событие, связанное с сокетом функцией WSAEventSelect, взводится при тех же условиях, при которых в очередь окна помещается сообщение при использовании WSAAsyncSelect.
Так, например, функция Recv взводит событие, если после её вызова в буфере сокета ещё остаются данные.
Но, с другой стороны, функция Recv не сбрасывает событие, если данных в буфере сокета нет. А так как сокетные события не сбрасываются автоматически функцией WSAWaitForMultipleEvents, программа всегда должна сбрасывать события сама
Существует весьма важное различие между использованием оконных сообщений и сокетных событий для оповещения о том, что происходит на сокете.
...
int WSAEnumNetworkEvents(
_In_ |
SOCKET s, |
_In_ |
WSAEVENT hEventObject, |
);_Out_ LPWSANETWORKEVENTS lpNetworkEvents
Функция WSAEnumNetworkEvents через параметр lpNetworkEvents возвращает информацию о том, какие события произошли на сокете S с момента последнего вызова этой функции для данного сокета (или с момента запуска программы, если функция вызывается в первый раз). Параметр hEventObject является необязательным. Он определяет сокетное событие, которое нужно сбросить.
typedef struct _WSANETWORKEVENTS {
long |
lNetworkEvents; |
int |
iErrorCode[FD_MAX_EVENTS]; |
} WSANETWORKEVENTS, *LPWSANETWORKEVENTS;
Массив iErrorCode содержит информацию об ошибках, которыми сопровождались события FD_XXX