accept()函式 Unix/Linux


名稱

accept - 接受連線通訊端上

內容簡介

#include <sys/types.h>
#include <sys/socket.h> 

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

描述說明

accept()系統呼叫用於基於連線的通訊端型別(SOCK_STREAM,SOCK_SEQPACKET)。提取完成連線佇列中的第一個連線請求,建立一個新的連線通訊端,並返回一個新的檔案描述符,指該通訊端。新建立的通訊端處於監聽狀態。原始通訊端 sockfd 不受此呼叫。

引數 sockfd 是一個通訊端系結到本地地址 bind(2) socket(2),已建立偵聽連線後 listen(2)。 

引數addr是一個指向結構sockaddr。被填充在此結構的對等通訊端的地址,作為已知的通訊層。地址返回 addr 的確切格式由通訊端的地址族(參見socket(2)及相應協定的手冊頁)。

addrlen 引數是一個值結果引數:最初它應該包含大小addr所指向的結構,在函式返回時將包含實際的長度(以位元組為單位)返回的地址。當沒有填寫addr是NULL。

如果沒有掛起的連線佇列,並沒有被標記為非阻塞通訊端,accept() 將阻塞,直到建立連線。如果通訊端被標記無阻塞,沒有未完成連線佇列上,accept() 失敗,並出現錯誤EAGAIN。

為了通知傳入連線在通訊端上,那麼可以使用select(2)或 orpoll(2)。當嚐試一個新的連線,然後可以呼叫accept() 獲取通訊端,連線一個可讀事件將被傳遞。另外,您還可以設定通訊端提供SIGIO活動發生在一個socket時,詳情參見socket(7)。

需要一個明確的確認,如 DECNET 對於某些協定,accept() 可以被看作是僅僅從佇列中取出下一個連線請求,不意味著確認。確認可以正常的讀或寫上新的檔案描述符,暗示和排斥反應,可通過關閉新的通訊端暗示。目前只有DECNet有這樣的Linux上的語意。

注意

可能並不總是等待一個連線後 SIGIO 交付 select(2) 或 poll(2) 因為連線可能已被刪除,被稱為非同步網路錯誤或另一個執行緒 accept() 返回一個可讀性事件。如果發生這種情況,那麼呼叫將阻塞等待下一個連線到達。

為了確保 accept() 從未阻塞,通過通訊端sockfd中需要有O_NONBLOCK標誌設定(參見socket(7))。

返回值

如果成功,accept()返回一個非負的整數,這是一個接受通訊端描述符。上的錯誤,則返回-1,errno設定為合適。

錯誤處理

Linux 的 accept() 傳遞已經掛起的網路錯誤,在新的socket accept() 錯誤程式碼。此行為不同於其他的BSD通訊端實現。對於可靠執行的應用程式應該檢測網路錯誤定義的協定後accept() ,並把它們像EAGAIN重試。在這些情況下,TCP/ IP是ENETDOWN ENOPROTOOPT EPROTO,EHOSTDOWN,ENONET,EHOSTUNREACH,EOPNOTSUPP,和ENETUNREACH的。 

錯誤

accept()可能失敗如下:

標籤 描述
EAGAINorEWOULDBLOCK The socket is marked non-blocking and no connections are present to be accepted.
EBADF The descriptor is invalid.
ECONNABORTED A connection has been aborted.
EINTR The system call was interrupted by a signal that was caught before a valid connection arrived.
EINVAL Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
EMFILE The per-process limit of open file descriptors has been reached.
ENFILE The system limit on the total number of open files has been reached.
ENOTSOCK The descriptor references a file, not a socket.
EOPNOTSUPP The referenced socket is not of typeSOCK_STREAM.

accept() 可能會失敗,如下:

標籤 描述
EFAULT The addr argument is not in a writable part of the user address space.
ENOBUFS, ENOMEM Not enough free memory. This often means that the memory allocation is limited by the socket bufferlimits, not by the system memory.
EPROTO Protocol error.

Linux accept() 可能會失敗,如下:

標籤 描述
EPERM Firewall rules forbid connection.

此外,新的通訊端的協定所定義的網路錯誤可能被返回。各種 Linux 核心可以返回其他錯誤,如ENOSR ESOCKTNOSUPPORT,EPROTONOSUPPORT ETIMEDOUT。在跟蹤過程中,可能會出現值ERESTARTSYS。

遵循於

SVr4, 4.4BSD (accept() first appeared in 4.2BSD).

注意

最初是作為一個'‘int *’'宣告 accept()的第三個引數(libc4和libc5和許多其他系統,如4.x的BSD,SunOS 4上,SGI);下一個POSIX.1g標準草案希望改變它變成了'size_t*',那是什麼它是在SunOS5。後來POSIX匯票“socklen_t*”,這樣做對單一Unix規範和glibc2。

另請參閱