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。