accept - 接受連接套接字上
#include <sys/types.h> #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); |
accept()系統(tǒng)調(diào)用用于基于連接的套接字類型(SOCK_STREAM,SOCK_SEQPACKET)。提取完成連接隊(duì)列中的第一個(gè)連接請(qǐng)求,創(chuàng)建一個(gè)新的連接套接字,并返回一個(gè)新的文件描述符,指該套接字。新創(chuàng)建的套接字處于監(jiān)聽狀態(tài)。原始套接字 sockfd 不受此調(diào)用。
參數(shù) sockfd 是一個(gè)套接字綁定到本地地址 bind(2) socket(2),已創(chuàng)建偵聽連接后 listen(2)。
參數(shù)addr是一個(gè)指向結(jié)構(gòu)sockaddr。被填充在此結(jié)構(gòu)的對(duì)等套接字的地址,作為已知的通信層。地址返回 addr 的確切格式由套接字的地址族(參見socket(2)及相應(yīng)協(xié)議的手冊(cè)頁)。
addrlen 參數(shù)是一個(gè)值結(jié)果參數(shù):最初它應(yīng)該包含大小addr所指向的結(jié)構(gòu),在函數(shù)返回時(shí)將包含實(shí)際的長(zhǎng)度(以字節(jié)為單位)返回的地址。當(dāng)沒有填寫addr是NULL。
如果沒有掛起的連接隊(duì)列,并沒有被標(biāo)記為非阻塞套接字,accept() 將阻塞,直到建立連接。如果套接字被標(biāo)記無阻塞,沒有未完成連接隊(duì)列上,accept() 失敗,并出現(xiàn)錯(cuò)誤EAGAIN。
為了通知傳入連接在套接字上,那么可以使用select(2)或 orpoll(2)。當(dāng)嘗試一個(gè)新的連接,然后可以調(diào)用accept() 獲取套接字,連接一個(gè)可讀事件將被傳遞。另外,您還可以設(shè)置套接字提供SIGIO活動(dòng)發(fā)生在一個(gè)socket時(shí),詳情參見socket(7)。
需要一個(gè)明確的確認(rèn),如 DECNET 對(duì)于某些協(xié)議,accept() 可以被看作是僅僅從隊(duì)列中取出下一個(gè)連接請(qǐng)求,不意味著確認(rèn)。確認(rèn)可以正常的讀或?qū)懮闲碌奈募枋龇凳竞团懦夥磻?yīng),可通過關(guān)閉新的套接字暗示。目前只有DECNet有這樣的Linux上的語義。
可能并不總是等待一個(gè)連接后 SIGIO 交付 select(2) 或 poll(2) 因?yàn)檫B接可能已被刪除,被稱為異步網(wǎng)絡(luò)錯(cuò)誤或另一個(gè)線程 accept() 返回一個(gè)可讀性事件。如果發(fā)生這種情況,那么調(diào)用將阻塞等待下一個(gè)連接到達(dá)。
為了確保 accept() 從未阻塞,通過套接字sockfd中需要有O_NONBLOCK標(biāo)志設(shè)置(參見socket(7))。
如果成功,accept()返回一個(gè)非負(fù)的整數(shù),這是一個(gè)接受套接字描述符。上的錯(cuò)誤,則返回-1,errno設(shè)置為合適。
Linux 的 accept() 傳遞已經(jīng)掛起的網(wǎng)絡(luò)錯(cuò)誤,在新的socket accept() 錯(cuò)誤代碼。此行為不同于其他的BSD套接字實(shí)現(xiàn)。對(duì)于可靠運(yùn)行的應(yīng)用程序應(yīng)該檢測(cè)網(wǎng)絡(luò)錯(cuò)誤定義的協(xié)議后accept() ,并把它們像EAGAIN重試。在這些情況下,TCP/ IP是ENETDOWN ENOPROTOOPT EPROTO,EHOSTDOWN,ENONET,EHOSTUNREACH,EOPNOTSUPP,和ENETUNREACH的。
accept()可能失敗如下:
標(biāo)簽 | 描述 |
---|---|
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() 可能會(huì)失敗,如下:
標(biāo)簽 | 描述 |
---|---|
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() 可能會(huì)失敗,如下:
標(biāo)簽 | 描述 |
---|---|
EPERM | Firewall rules forbid connection. |
此外,新的套接字的協(xié)議所定義的網(wǎng)絡(luò)錯(cuò)誤可能被返回。各種 Linux 內(nèi)核可以返回其他錯(cuò)誤,如ENOSR ESOCKTNOSUPPORT,EPROTONOSUPPORT ETIMEDOUT。在跟蹤過程中,可能會(huì)出現(xiàn)值ERESTARTSYS。
SVr4, 4.4BSD (accept() first appeared in 4.2BSD).
最初是作為一個(gè)'‘int *’'聲明 accept()的第三個(gè)參數(shù)(libc4和libc5和許多其他系統(tǒng),如4.x的BSD,SunOS 4上,SGI);下一個(gè)POSIX.1g標(biāo)準(zhǔn)草案希望改變它變成了'size_t*',那是什么它是在SunOS5。后來POSIX匯票“socklen_t*”,這樣做對(duì)單一Unix規(guī)范和glibc2。