Функция WSAAccept (winsock2.h)
Функция WSAAccept условно принимает соединение на основе возвращаемого значения функции условия, обеспечивает качество спецификаций потока обслуживания и позволяет передавать данные подключения.
Синтаксис
SOCKET WSAAPI WSAAccept(
[in] SOCKET s,
[out] sockaddr *addr,
[in, out] LPINT addrlen,
[in] LPCONDITIONPROC lpfnCondition,
[in] DWORD_PTR dwCallbackData
);
Параметры
[in] s
Дескриптор, идентифицирующий сокет, прослушивающий подключения после вызова функции прослушивания .
[out] addr
Необязательный указатель на структуру sockaddr , которая получает адрес подключающейся сущности, как известно на уровне связи. Точный формат параметра addr определяется семейством адресов, установленным при создании сокета.
[in, out] addrlen
Необязательный указатель на целое число, содержащее длину структуры sockaddr, на которую указывает параметр addr , в байтах.
[in] lpfnCondition
Адрес необязательной функции условия, указанной приложением, которая принимает или отклоняет решение на основе сведений о вызывающем объекте, передаваемых в качестве параметров, и при необходимости создает или присоединяет группу сокетов, присваивая соответствующее значение результирующим параметру g этой функции. Если этот параметр имеет значение NULL, то функция условия не вызывается.
[in] dwCallbackData
Данные обратного вызова, передаваемые в определяемую приложением функцию условия в качестве значения параметра dwCallbackData, передаваемого в функцию условия. Этот параметр применим, только если параметр lpfnCondition не имеет значения NULL. Этот параметр не интерпретируется сокетами Windows.
Возвращаемое значение
Если ошибка не возникает, WSAAccept возвращает значение типа SOCKET, которое является дескриптором для принятого сокета. В противном случае возвращается значение INVALID_SOCKET, а определенный код ошибки можно получить, вызвав WSAGetLastError.
Целое число, на которое ссылается addrlen , изначально содержит объем пространства, на который указывает addr. При возврате он будет содержать фактическую длину возвращаемого адреса в байтах.
Код ошибки | Значение |
---|---|
Предпринята попытка получить доступ к сокету способом, запрещенным его разрешениями на доступ. Эта ошибка возвращается, если время ожидания запроса на подключение истекло или было отозвано. | |
Не удалось подключиться, так как целевой компьютер отказался от него. Эта ошибка возвращается, если запрос на подключение был принудительно отклонен, как указано в возвращаемом значении функции условия (CF_REJECT). | |
существующее соединение было принудительно завершено удаленным узлом. Эта ошибка возвращается при указании входящего подключения, но впоследствии была прервана удаленным одноранговым узелом перед принятием вызова. | |
Система обнаружила недопустимый адрес указателя при попытке использовать аргумент указателя в вызове. Эта ошибка возвращается, если параметр addrlen слишком мал или addr или lpfnCondition не является частью адресного пространства пользователя. | |
Операция блокировки была прервана вызовом WSACancelBlockingCall. Эта ошибка возвращается, если блокирующий вызов Windows Sockets 1.1 был отменен через WSACancelBlockingCall. | |
В данный момент выполняется блокирующая операция. Эта ошибка возвращается, если выполняется блокирующий вызов Windows Sockets 1.1. | |
Указан недопустимый аргумент. Эта ошибка возвращается, если прослушивание не было вызвано до WSAAccept, возвращаемое значение функции условия не является допустимым или в любом случае, когда указанный сокет находится в недопустимом состоянии. | |
Слишком много открытых сокетов. Эта ошибка возвращается, если очередь не является непустой при входе в WSAAccept и нет доступных дескрипторов сокетов. | |
Операция на сокете обнаружила отключение сети. Эта ошибка возвращается в случае сбоя сетевой подсистемы. | |
Не удалось выполнить операцию с сокетом, так как в системе недостаточно места в буфере или из-за переполнения очереди. Эта ошибка возвращается, если буфер недоступен. | |
Предпринята попытка выполнить операцию с тем, что не является сокетом. Эта ошибка возвращается, если дескриптор сокета, переданный в параметре s , не является сокетом. | |
Семейство протоколов не настроено в системе или для него не существует реализации. Эта ошибка возвращается, если указанный сокет не является типом, поддерживающим службу, ориентированную на подключение. | |
Неблокирующая операция сокета не может быть завершена немедленно. Эта ошибка возвращается, если сокет помечается как неблокирующий и нет подключений для принятия. | |
Либо приложение не вызывало WSAStartup, либо WSAStartup завершилось сбоем. Эта ошибка возвращается из-за успешного вызова функции WSAStartup dit не происходит до использования этой функции. | |
Обычно это временная ошибка при разрешении имени узла, и она означает, что локальный сервер не получил ответа от заслуживающего доверия сервера. Эта ошибка возвращается, если принятие запроса на подключение было отложено, как указано в возвращаемом значении функции условия (CF_DEFER). |
Комментарии
Функция WSAAccept извлекает первое подключение в очереди ожидающих подключений в сокетах и проверяет его на соответствие функции условия при условии, что указана функция условия (т. е. не NULL). Если функция condition возвращает CF_ACCEPT, WSAAccept создает новый сокет. Вновь созданный сокет имеет те же свойства, что и сокеты, включая асинхронные события, зарегистрированные с помощью WSAsyncSelect или WSAEventSelect. Если функция condition возвращает CF_REJECT, WSAAccept отклоняет запрос на подключение. Функция condition выполняется в том же потоке, что и эта функция, и должна вернуться как можно скорее. Если решение не может быть принято немедленно, функция условия должна возвращать CF_DEFER, чтобы указать, что решение не было принято, и поставщик услуг не должен предпринимать никаких действий по этому запросу на подключение. Когда приложение будет готово к выполнению действия с запросом на подключение, оно снова вызовет WSAAccept и вернет CF_ACCEPT или CF_REJECT в качестве значения, возвращаемого функцией условия.
Сокет в режиме по умолчанию (блокировка) будет блокироваться до тех пор, пока не будет установлено подключение, когда приложение вызывает WSAAccept и в очереди нет ожидающих подключений.
Сокет в неблокированном режиме (блокировка) завершается сбоем с ошибкой WSAEWOULDBLOCK , когда приложение вызывает WSAAccept и в очереди нет ожидающих подключений. После успешного выполнения WSAAccept и возврата нового дескриптора сокета принятый сокет нельзя использовать для приема дополнительных подключений. Исходный сокет остается открытым и прослушивает новые запросы на подключение.
Параметр addr — это результирующий параметр, который заполняется адресом подключающейся сущности, как известно уровню связи. Точный формат параметра addr определяется семейством адресов, в котором происходит обмен данными. Addrlen является параметром значения и результата; Изначально он должен содержать объем пространства, на который указывает addr. При возврате он будет содержать фактическую длину (в байтах) возвращенного адреса. Этот вызов используется с типами сокетов, ориентированными на подключение, такими как SOCK_STREAM. Если аргумент addr и (или ) addrlen равен NULL, то сведения об удаленном адресе принятого сокета не возвращаются. В противном случае эти два параметра будут заполнены, если подключение будет успешно принято.
Прототип функции условия определен в файле заголовка Winsock2.h
как LPCONDITIONPROC, как показано ниже.
int CALLBACK
ConditionFunc(
IN LPWSABUF lpCallerId,
IN LPWSABUF lpCallerData,
IN OUT LPQOS lpSQOS,
IN OUT LPQOS lpGQOS,
IN LPWSABUF lpCalleeId,
IN LPWSABUF lpCalleeData,
OUT GROUP FAR * g,
IN DWORD_PTR dwCallbackData
);
ConditionFunc — это заполнитель для функции обратного вызова, указанной приложением. Фактическая функция условия должна находиться в библиотеке DLL или модуле приложения. Он экспортируется в файл определения модуля.
Параметр lpCallerId указывает на структуру WSABUF, содержащую адрес подключающейся сущности, где его параметр len — это длина буфера в байтах, а параметр buf — указатель на буфер. lpCallerData — это параметр значения, содержащий любые пользовательские данные. Сведения в этих параметрах отправляются вместе с запросом на подключение. Если идентификация вызывающего объекта или данные вызывающей стороны недоступны, соответствующие параметры будут иметь значение NULL. Многие сетевые протоколы не поддерживают данные вызывающего абонента во время подключения. Ожидается, что большинство обычных сетевых протоколов будут поддерживать сведения об идентификаторе вызывающего абонента во время запроса подключения. Часть Buf WSABUF , на которую указывает lpCallerId , указывает на sockaddr. Структура sockaddr интерпретируется в соответствии с семейством адресов (обычно путем приведения sockaddr к определенному типу, относямуся к семейству адресов).
Параметр lpSQOS ссылается на структуры FLOWSPEC для сокетов, заданных вызывающим объектом, по одному для каждого направления, за которым следуют все дополнительные параметры, зависящие от поставщика. Значения спецификации потока отправки или получения будут игнорироваться для любых однонаправленных сокетов. Значение NULL указывает, что качество обслуживания, предоставляемое вызывающим абонентом, отсутствует и что согласование невозможно. Указатель lpSQOS, отличный от NULL, указывает, что требуется согласование качества обслуживания или что поставщик готов принять качество запроса на обслуживание без согласования.
Параметр lpGQOS зарезервирован и должен иметь значение NULL. (зарезервировано для будущего использования с группами сокетов) ссылается на структуру FLOWSPEC для группы сокетов, которую нужно создать вызывающей стороне, по одному для каждого направления, за которой следуют любые дополнительные параметры, относящиеся к поставщику. Значение NULL для lpGQOS указывает на отсутствие качества обслуживания группы, указанной вызывающим объектом. Если необходимо выполнить согласование, можно вернуть сведения о качестве обслуживания.
lpCalleeId — это параметр, содержащий локальный адрес подключенной сущности. Часть buf WSABUF, на которую указывает lpCalleeId , указывает на структуру sockaddr . Структура sockaddr интерпретируется в соответствии с семейством адресов (как правило, путем приведения sockaddr к определенному типу, относямуся к семейству адресов, например структура sockaddr_in).
lpCalleeData — это результирующий параметр, используемый функцией условия для передачи пользовательских данных в подключающуюся сущность. lpCalleeData-len> изначально содержит длину буфера, выделенного поставщиком услуг и на который указывает lpCalleeData-buf>. Нулевое значение означает, что передача пользовательских данных обратно вызывающей стороне не поддерживается. Функция condition должна скопировать данные в lpCalleeData-len> в байты данных в lpCalleeData-buf>, а затем обновить lpCalleeData-len>, чтобы указать фактическое количество переданных байтов. Если данные пользователя не передаются обратно вызывающей стороне, функция condition должна задать для lpCalleeData-len> значение 0. Формат всех данных адреса и пользователя зависит от семейства адресов, к которому принадлежит сокет.
Параметр g назначается в функции condition для указания любого из следующих действий:
- Если g — это существующий идентификатор группы сокетов, добавьте в эту группу s при условии выполнения всех требований, установленных этой группой.
- Если g = SG_UNCONSTRAINED_GROUP, создайте группу неограниченного сокета и укажите в качестве первого члена.
- Если g = SG_CONSTRAINED_GROUP, создайте ограниченную группу сокетов и укажите в качестве первого члена.
- Если g = ноль, операция группы не выполняется.
Значение параметра dwCallbackData , передаваемое функции condition, — это значение, переданное в качестве параметра dwCallbackData в исходном вызове WSAAccept . Это значение интерпретируется только клиентом сокета Windows версии 2. Это позволяет клиенту передавать некоторые сведения о контексте с сайта вызова WSAAccept через функцию condition. Это также предоставляет функцию условия с любыми дополнительными сведениями, необходимыми для определения того, следует ли принимать соединение. Типичным способом использования является передача указателя (подходящего приведения) в структуру данных, содержащую ссылки на определяемые приложением объекты, с которыми связан этот сокет.
Пример кода
В следующем примере показано использование функции WSAAccept .#include <winsock2.h>
#include <stdio.h>
#include <windows.h>
/* Define an example conditional function that depends on the pQos field */
int CALLBACK ConditionAcceptFunc(
LPWSABUF lpCallerId,
LPWSABUF lpCallerData,
LPQOS pQos,
LPQOS lpGQOS,
LPWSABUF lpCalleeId,
LPWSABUF lpCalleeData,
GROUP FAR * g,
DWORD_PTR dwCallbackData
)
{
if (pQos != NULL) {
RtlZeroMemory(pQos, sizeof(QOS));
return CF_ACCEPT;
} else
return CF_REJECT;
}
int main() {
/* Declare and initialize variables */
WSADATA wsaData;
SOCKET ListenSocket, AcceptSocket;
struct sockaddr_in saClient;
int iClientSize = sizeof(saClient);
u_short port = 27015;
char* ip;
sockaddr_in service;
int error;
/* Initialize Winsock */
error = WSAStartup(MAKEWORD(2,2), &wsaData);
if (error) {
printf("WSAStartup() failed with error: %d\n", error);
return 1;
}
/* Create a TCP listening socket */
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ListenSocket == INVALID_SOCKET) {
printf("socket() failed with error: %d\n", WSAGetLastError() );
WSACleanup();
return 1;
}
/*-----------------------------------------
* Set up the sock addr structure that the listening socket
* will be bound to. In this case, the structure holds the
* local IP address and the port specified. */
service.sin_family = AF_INET;
service.sin_port = htons(port);
hostent* thisHost;
thisHost = gethostbyname("");
ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
service.sin_addr.s_addr = inet_addr(ip);
/*-----------------------------------------
* Bind the listening socket to the IP address.
* and port number specified by the sockaddr structure. */
error = bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
if (error == SOCKET_ERROR) {
printf("bind() failed with error: %d\n", WSAGetLastError() );
closesocket(ListenSocket);
WSACleanup();
return 1;
}
/* Make the socket listen for incoming connection requests */
error = listen(ListenSocket, 1);
if (error == SOCKET_ERROR) {
printf("listen() failed with error: %d\n", WSAGetLastError() );
closesocket(ListenSocket);
WSACleanup();
return 1;
}
printf("Listening...\n");
/*-----------------------------------------
* Accept an incoming connection request on the
* listening socket and transfer control to the
* accepting socket. */
AcceptSocket = WSAAccept(ListenSocket, (SOCKADDR*) &saClient, &iClientSize,
&ConditionAcceptFunc, NULL);
/* Now do some work with the AcceptSocket
* At this point, the application could
* handle data transfer on the socket, or other socket
* functionality.*/
/* Then clean up and quit */
closesocket(AcceptSocket);
closesocket(ListenSocket);
WSACleanup();
return 0;
}
Windows Phone 8. Эта функция поддерживается для приложений Магазина Windows Phone на Windows Phone 8 и более поздних версиях.
Windows 8.1 и Windows Server 2012 R2. Эта функция поддерживается для приложений Магазина Windows на Windows 8.1, Windows Server 2012 R2 и более поздних версиях.
Требования
Требование | Значение |
---|---|
Минимальная версия клиента | Windows 8.1, Windows Vista [классические приложения | Приложения UWP] |
Минимальная версия сервера | Windows Server 2003 [классические приложения | Приложения UWP] |
Целевая платформа | Windows |
Header | winsock2.h |
Библиотека | Ws2_32.lib |
DLL | Ws2_32.dll |
См. также раздел
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по