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 套接字 1.1 调用已通过 WSACancelBlockingCall 取消。
WSAEINVAL
接受之前未调用 listen 函数。
WSAEINPROGRESS
阻止 Windows Sockets 1.1 调用正在进行,或者服务提供程序仍在处理回调函数。
WSAEMFILE
队列在 输入接受时 为非空,并且没有可用的描述符。
WSAENETDOWN
网络子系统失败。
WSAENOBUFS
未提供任何缓冲区空间。
WSAENOTSOCK
:描述符不是套接字。
WSAEOPNOTSUPP
:引用的套接字不是支持面向连接的服务的类型。
WSAEWOULDBLOCK
:套接字标记为非阻止,没有要接受的连接。

注解

accept 函数提取套接字 上挂起连接队列中的第一连接。 然后,它会创建并返回新套接字的句柄。 新创建的套接字是将处理实际连接的套接字;它具有 与套接字相同的属性,包括向 WSAAsyncSelectWSAEventSelect 函数注册的异步事件。

如果队列中没有挂起的连接,并且套接字标记为阻塞,则 accept 函数可以阻止调用方,直到存在连接。 如果套接字标记为非阻止,并且队列中没有挂起的连接, 则接受 将返回如下所述的错误。 成功完成 accept 返回新的套接字句柄后,接受的套接字不能用于接受更多连接。 原始套接字保持打开状态,并侦听新的连接请求。

参数 添加器 是一个结果参数,它用连接实体的地址填充,如通信层所称。 addr 参数的确切格式由发生通信的地址系列确定。 addrlen 是 value-result 参数;它最初应包含 addr 指向的空间量;返回时,它将包含返回的地址的实际长度 () 字节。

accept 函数与面向连接的套接字类型(如 SOCK_STREAM)一起使用。 如果 addr 和/或 addrlen 等于 NULL,则不会返回有关接受套接字的远程地址的信息。

注意 发出阻止 Winsock 调用(如 accept)时,Winsock 可能需要等待网络事件,然后调用才能完成。 在这种情况下,Winsock 执行可发出警报的等待, (在同一线程上计划的 APC) 异步过程调用可能会中断该等待。 在 APC 内发出另一个阻止 Winsock 调用,该调用中断了同一线程上正在进行的阻止 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 说明

以下是与连接设置相关的重要问题,在将异步传输模式 (ATM) 与 Windows 套接字 2 配合使用时,必须考虑这些问题:

  • acceptWSAAccept 函数不一定设置远程地址和地址长度参数。 因此,使用 ATM 时,调用方应使用 WSAAccept 函数并将ATM_CALLING_PARTY_NUMBER_IE放在 QoS 结构的 ProviderSpecific 成员中,该成员本身包含在根据 WSAAccept 使用的回调函数的 lpSQOS 参数中。
  • 使用 accept 函数时,请注意,在连接建立已遍历发送方和接收方之间的整个距离之前,函数可能会返回 。 这是因为 accept 函数在收到 CONNECT ACK 消息后立即返回 ;在 ATM 中,一旦将 CONNECT 消息处理 (,路径中的下一个开关就会返回 CONNECT ACK 消息,而不是最终) 建立连接的终结点发送 CONNECT ACK。 因此,应用程序应意识到,如果在收到 CONNECT ACK 消息后立即发送数据,则可能会丢失数据,因为可能尚未在发送方和接收方之间建立连接。

Windows 8.1Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。

要求

要求
最低受支持的客户端 Windows 8.1、Windows Vista [桌面应用 |UWP 应用]
最低受支持的服务器 Windows Server 2003 [桌面应用 | UWP 应用]
目标平台 Windows
标头 winsock2.h
Library Ws2_32.lib
DLL Ws2_32.dll

另请参阅

WSAAccept

WSAAsyncSelect

Winsock 函数

Winsock 参考

bind

connect

listen

select

sockaddr

socket