Поделиться через


Функция accept (winsock2.h)

Функция accept разрешает входящую попытку подключения к сокету.

Синтаксис

SOCKET WSAAPI accept(
  [in]      SOCKET   s,
  [out]     sockaddr *addr,
  [in, out] int      *addrlen
);

Параметры

[in] s

Дескриптор, идентифицирующий сокет, помещенный в состояние прослушивания с помощью функции прослушивания . Соединение фактически выполняется с помощью сокета, возвращаемого методом accept.

[out] addr

Необязательный указатель на буфер, который получает адрес подключающейся сущности, как известно для уровня связи. Точный формат параметра addr определяется семейством адресов, которое было установлено при создании сокета из структуры sockaddr .

[in, out] addrlen

Необязательный указатель на целое число, содержащее длину структуры, на которую указывает параметр addr .

Возвращаемое значение

Если ошибка не возникает, функция accept возвращает значение типа SOCKET , которое является дескрипторовом для нового сокета. Это возвращаемое значение является дескриптором для сокета, с которым установлено фактическое соединение.

В противном случае возвращается значение INVALID_SOCKET , а конкретный код ошибки можно получить, вызвав WSAGetLastError.

Целое число, на которое ссылается addrlen, изначально содержит объем пространства, на который указывает addr. При возврате он будет содержать фактическую длину возвращенного адреса в байтах.

Код ошибки Значение
WSANOTINITIALISED
Перед использованием этой функции должен произойти успешный вызов WSAStartup .
WSAECONNRESET
Было указано входящее подключение, но впоследствии было прервано удаленным одноранговым узлом перед принятием вызова.
WSAEFAULT
Параметр addrlen слишком мал или addr не является допустимой частью адресного пространства пользователя.
WSAEINTR
Блокирующий вызов Windows Sockets 1.1 был отменен через WSACancelBlockingCall.
WSAEINVAL
Функция прослушивания не была вызвана до принятия.
WSAEINPROGRESS
Выполняется блокирующий вызов Windows Sockets 1.1 или поставщик услуг по-прежнему обрабатывает функцию обратного вызова.
WSAEMFILE
Очередь не является непустой, когда запись принимается , и дескрипторы отсутствуют.
WSAENETDOWN
Произошел сбой сетевой подсистемы.
WSAENOBUFS
Нет свободного места в буфере.
WSAENOTSOCK
Дескриптор не является сокетом.
WSAEOPNOTSUPP
Указанный сокет не является типом, поддерживающим службу, ориентированную на подключение.
WSAEWOULDBLOCK
Сокет помечается как неблокивный, и подключения для принятия отсутствуют.

Комментарии

Функция accept извлекает первое подключение в очереди ожидающих подключений в сокетах. Затем он создает и возвращает дескриптор новому сокету. Только что созданный сокет — это сокет, который будет обрабатывать фактическое соединение; Он имеет те же свойства, что и сокеты, включая асинхронные события, зарегистрированные с помощью функций WSAsyncSelect или WSAEventSelect .

Функция accept может блокировать вызывающий объект до тех пор, пока не будет установлено подключение, если в очереди нет ожидающих подключений и сокет помечается как блокирующий. Если сокет помечен как неблокивный и в очереди нет ожидающих подключений, функция accept возвращает ошибку, как описано ниже. После успешного завершения метода accept возвращается новый дескриптор сокета, принятый сокет нельзя использовать для приема дополнительных подключений. Исходный сокет остается открытым и ожидает новых запросов на подключение.

Надстройка параметра — это результирующий параметр, который заполняется адресом подключающейся сущности, как известно уровню связи. Точный формат параметра addr определяется семейством адресов, в котором происходит обмен данными. Addrlen является параметром value-result; он должен изначально содержать объем пространства, на который указывает addr; при возврате он будет содержать фактическую длину (в байтах) возвращенного адреса.

Функция accept используется с типами сокетов, ориентированными на подключение, такими как SOCK_STREAM. Если addr и (или ) addrlen равны NULL, то сведения об удаленном адресе принятого сокета не возвращаются.

Примечание При выполнении блокирующего вызова Winsock, например accept, Winsock может потребоваться дождаться сетевого события, прежде чем вызов сможет завершиться. В этой ситуации Winsock выполняет оповещенное ожидание, которое может быть прервано асинхронным вызовом процедуры (APC), запланированным в том же потоке. Выполнение другого блокирующего вызова Winsock внутри APC, который прервал текущий блокирующий вызов Winsock в том же потоке, приведет к неопределенному поведению, и клиенты Winsock никогда не должны пытаться его выполнять.
 

Пример кода

В следующем примере показано использование функции accept .
#ifndef UNICODE
#define UNICODE
#endif

#include <winsock2.h>
#include <WS2tcpip.h>
#include <stdio.h>
#include <windows.h>

// Need to link with Ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

int wmain(void)
{

    //----------------------
    // Initialize Winsock.
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"WSAStartup failed with error: %ld\n", iResult);
        return 1;
    }
    //----------------------
    // Create a SOCKET for listening for
    // incoming connection requests.
    SOCKET ListenSocket;
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    //----------------------
    // The sockaddr_in structure specifies the address family,
    // IP address, and port for the socket that is being bound.
    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_port = htons(27015);
    inet_pton(AF_INET, "127.0.0.1", &service.sin_addr);

    if (bind(ListenSocket,
             (SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR) {
        wprintf(L"bind failed with error: %ld\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    //----------------------
    // Listen for incoming connection requests.
    // on the created socket
    if (listen(ListenSocket, 1) == SOCKET_ERROR) {
        wprintf(L"listen failed with error: %ld\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    //----------------------
    // Create a SOCKET for accepting incoming requests.
    SOCKET AcceptSocket;
    wprintf(L"Waiting for client to connect...\n");

    //----------------------
    // Accept the connection.
    AcceptSocket = accept(ListenSocket, NULL, NULL);
    if (AcceptSocket == INVALID_SOCKET) {
        wprintf(L"accept failed with error: %ld\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    } else
        wprintf(L"Client connected.\n");

    // No longer need server socket
    closesocket(ListenSocket);

    WSACleanup();
    return 0;
}


Другой пример, в котором используется функция accept, см. в разделе начало работы With Winsock.

Примечания для банкомата

Ниже приведены важные проблемы, связанные с настройкой подключения, которые необходимо учитывать при использовании режима асинхронной передачи (ATM) с windows Sockets 2.

  • Функции accept и WSAAccept не обязательно задают параметры удаленного адреса и длины адреса. Таким образом, при использовании ATM вызывающий объект должен использовать функцию WSAAccept и поместить ATM_CALLING_PARTY_NUMBER_IE в член ProviderSpecific структуры QoS , который сам включен в параметр lpSQOS функции обратного вызова, используемой в соответствии с WSAAccept.
  • При использовании функции accept поймите, что функция может возвращать значение до того, как соединение будет проходить через все расстояние между отправителем и получателем. Это связано с тем, что функция accept возвращается сразу после получения сообщения CONNECT ACK. в ATM сообщение CONNECT ACK возвращается следующим переключателем в пути, как только сообщение CONNECT обрабатывается (а не сообщение CONNECT ACK отправляется конечным узлом, к которому в конечном итоге установлено соединение). Таким образом, приложения должны понимать, что если данные отправляются сразу после получения сообщения CONNECT ACK, возможна потеря данных, так как подключение между отправителем и получателем не было установлено.

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

См. также раздел

WSAAccept

WSAsyncSelect

Функции Winsock

Справочник по Winsock

bind

connect;

listen

select

sockaddr

Сокета