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。
另請參閱
bind (2)
connect (2)
listen (2)
select (2)
socket (2)