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 函式會擷取套接字上擱置連線佇列上的第一個連線。 然後,它會建立並傳回新套接字的句柄。 新建立的套接字是將處理實際連線的套接字;它具有 與套接字相同的屬性,包括向 WSAAsyncSelectWSAEventSelect 函式註冊的異步事件。

如果佇列上沒有暫止連線,且套接字標示為封鎖, 接受 函式可以封鎖呼叫端,直到連接存在為止。 如果套接字標示為非封鎖,且佇列上沒有擱置的連線, 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 Sockets 2 時必須考慮:

  • acceptWSAAccept 函式不一定設定遠端位址和地址長度參數。 因此,使用 ATM 時,呼叫端應該使用 WSAAccept 函式,並將ATM_CALLING_PARTY_NUMBER_IE放在 QoS 結構的 ProviderSpecific 成員中,其本身會包含在根據 WSAAccept 使用的回呼函式的 lpSQOS 參數中。
  • 使用 accept 函式時,請注意,在連線建立之前,函式可能會傳回給傳送者和接收者之間的整個距離。 這是因為在接收 CONNECT ACK 訊息時 ,accept 函式會立即傳回;在 ATM 中,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
程式庫 Ws2_32.lib
Dll Ws2_32.dll

另請參閱

WSAAccept

WSAAsyncSelect

Winsock 函式

Winsock 參考

bind

connect

listen

select

sockaddr

socket