Функция 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, которая получает адрес подключаемой сущности, как известно для уровня связи. Точный формат параметра надстройки определяется семейством адресов, установленным при создании сокета.
[in, out] addrlen
Необязательный указатель на целое число, содержащее длину
[in] lpfnCondition
Адрес необязательной функции условия, указанной приложением, которая будет принимать или отклонять решение на основе информации вызывающего объекта, переданной в качестве параметров, и при необходимости создайте или присоедините группу сокетов, назначив соответствующее значение параметру результата g этой функции. Если этот параметр null, функция условия не вызывается.
[in] dwCallbackData
Данные обратного вызова, передаваемые в функцию условия, указанной приложением, в качестве значения параметра dwCallbackData, переданного функции условия. Этот параметр применим только в том случае, если параметр lpfnCondition не NULL. Этот параметр не интерпретируется сокетами Windows.
Возвращаемое значение
Если ошибка не возникает, WSAAccept возвращает значение типа SOCKET, которое является дескриптором для принятого сокета. В противном случае возвращается значение INVALID_SOCKET, а определенный код ошибки можно получить путем вызова WSAGetLastError.
Целое число, на которое ссылается addrlen изначально содержится пространство, на которое указывает надстройки. При возврате он будет содержать фактическую длину в байтах возвращаемого адреса.
Код ошибки | Значение |
---|---|
Предпринята попытка получить доступ к сокету путем, запрещенному его разрешениями на доступ. Эта ошибка возвращается, если предлагаемый запрос подключения истек или был снят. | |
Подключение не может быть сделано, так как целевой компьютер активно отказался от него. Эта ошибка возвращается, если запрос на подключение был принудительно отклонен, как указано в возвращаемом значении функции условия (CF_REJECT). | |
Существующее подключение было принудительно закрыто удаленным узлом. Эта ошибка возвращается из входящего подключения, но впоследствии была завершена удаленным одноранговым узлом до принятия вызова. | |
Система обнаружила недопустимый адрес указателя при попытке использовать аргумент указателя в вызове. Эта ошибка возвращается из параметра addrlen слишком мал или надстройки или lpfnCondition не входит в адресное пространство пользователя. | |
Блокировка была прервана вызовом WSACancelBlockingCall. Эта ошибка возвращается, если блокировка вызова сокетов Windows 1.1 была отменена через WSACancelBlockingCall. | |
В настоящее время выполняется операция блокировки. Эта ошибка возвращается, если выполняется блокировка вызова сокетов Windows 1.1. | |
Указан недопустимый аргумент. Эта ошибка возвращается, если прослушивание не было вызвано до WSAAccept, возвращаемое значение функции условия не является допустимым или в любом случае, если указанный сокет находится в недопустимом состоянии. | |
Слишком много открытых сокетов. Эта ошибка возвращается, если очередь не является простой при записи для WSAAccept и нет дескрипторов сокетов. | |
Операция сокета столкнулась с мертвой сетью. Эта ошибка возвращается, если сетевая подсистема завершилась ошибкой. | |
Не удалось выполнить операцию сокета, так как в системе недостаточно буферного пространства или из-за того, что очередь была заполнена. Эта ошибка возвращается, если буферное пространство недоступно. | |
Операция была предпринята на то, что не является сокетом. Эта ошибка возвращается, если дескриптор сокета, переданный в параметре |
|
Семейство протоколов не настроено в системе или отсутствует реализация для нее. Эта ошибка возвращается, если указанный сокет не является типом, поддерживающим службу, ориентированную на подключение. | |
Неблокирующая операция сокета не может быть завершена немедленно. Эта ошибка возвращается, если сокет помечается как неблокировка и не будут приниматься подключения. | |
Либо приложение не вызывает WSAStartup, либо WSAStartup. Эта ошибка возвращает успешный вызов функции WSAStartup не возникает перед использованием этой функции. | |
Обычно это временная ошибка во время разрешения имен узла и означает, что локальный сервер не получил ответ от авторитетного сервера. Эта ошибка возвращается, если принятие запроса подключения было отложено, как указано в возвращаемом значении функции условия (CF_DEFER). |
Замечания
Функция WSAAccept
Сокет в режиме по умолчанию (блокировка) блокируется до тех пор, пока подключение не появится, когда приложение вызывает WSAAccept, и в очереди нет ожидающих подключений.
Сокет в режиме неблокировки (блокировка) завершается ошибкой WSAEWOULDBLOCK при вызове приложения WSAAccept и отсутствие подключений в очереди. После того как WSAAccept успешно и возвращает новый дескриптор сокета, приемленный сокет нельзя использовать для принятия дополнительных подключений. Исходный сокет остается открытым и прослушивает новые запросы на подключение.
Параметр надстройки
Прототип функции условия определен в файле заголовка 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. Многие сетевые протоколы не поддерживают данные абонента во время подключения. Большинство обычных сетевых протоколов могут поддерживать сведения об идентификаторе вызывающего абонента во время запроса подключения. Часть WSABUF указывает на lpCallerId указывает на sockaddr. Структура sockaddr интерпретируется в соответствии с его семейством адресов (как правило, путем приведения sockaddr к определенному типу, конкретному семейству адресов).
Параметр
Параметр
lpCalleeId — это параметр, содержащий локальный адрес подключенной сущности. буф части WSABUF, на которую указывает lpCalleeId указывает на структуру sockaddr. Структура sockaddr интерпретируется в соответствии со своей адресной семьей (как правило, путем приведения sockaddr к определенному типу, конкретному семейству адресов, например структуре sockaddr_in).
lpCalleeData — это параметр результата, используемый функцией условия для предоставления пользовательских данных обратно в сущность подключения. lpCalleeData->len изначально содержит длину буфера, выделенного поставщиком услуг, и указывает на lpCalleeData->buf. Значение нуля означает, что передача пользовательских данных обратно вызывающей стороне не поддерживается. Функция условия должна скопировать до lpCalleeData->len байт данных в lpCalleeData->buf, а затем обновить lpCalleeData->len, чтобы указать фактическое количество переданных байтов. Если пользовательские данные не передаются обратно вызывающей стороне, функция условия должна задать значение lpCalleeData->len равным нулю. Формат всех данных адреса и пользователя зависит от семейства адресов, к которому принадлежит сокет.
Параметр g назначается в функции условия, чтобы указать любое из следующих действий:
- Если
g является существующим идентификатором группы сокетов, добавьтев эту группу, если выполнены все требования, заданные этой группой. - Если
g = SG_UNCONSTRAINED_GROUP, создайте группу без ограничений сокета ив качестве первого члена. - Если
g = SG_CONSTRAINED_GROUP, создайте группу ограниченного сокета ив качестве первого члена. - Если g = ноль, операция группы не выполняется.
Значение параметра
пример кода
В следующем примере показано использование функции 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] |
целевая платформа | Виндоус |
заголовка | winsock2.h |
библиотеки |
Ws2_32.lib |
DLL | Ws2_32.dll |
См. также
Справочник
подключение
сокета