名稱
accept()
接收一個套接字中已建立的連接
使用格式
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
功能參數描述
accept()系統調用主要用在基於連接的套接字類型,比如SOCK_STREAM和SOCK_SEQPACKET。它提取出所監聽套接字的等待連接隊列中第一個連接請求,創建一個新的套接字,並返回指向該套接字的文件描述符。新建立的套接字不在監聽狀態,原來所監聽的套接字也不受該系統調用的影響。
備注:新建立的套接字准備發送send()和接收數據recv()。
參數:
sockfd, 利用系統調用socket()建立的套接字描述符,通過bind()綁定到一個本地地址(一般為服務器的套接字),並且通過listen()一直在監聽連接;
addr, 指向struct sockaddr的指針,該結構用通訊層服務器對等套接字的地址(一般為客戶端地址)填寫,返回地址addr的確切格式由套接字的地址類別(比如TCP或UDP)決定;若addr為NULL,沒有有效地址填寫,這種情況下,addrlen也不使用,應該置為NULL;
備注:addr是個指向局部數據結構sockaddr_in的指針,這就是要求接入的信息本地的套接字(地址和指針)。
addrlen, 一個值結果參數,調用函數必須初始化為包含addr所指向結構大小的數值,函數返回時包含對等地址(一般為服務器地址)的實際數值;
備注:addrlen是個局部整形變量,設置為sizeof(struct sockaddr_in)。
如果隊列中沒有等待的連接,套接字也沒有被標記為Non-blocking,accept()會阻塞調用函數直到連接出現;如果套接字被標記為Non-blocking,隊列中也沒有等待的連接,accept()返回錯誤EAGAIN或EWOULDBLOCK。
備注:一般來說,實現時accept()為阻塞函數,當監聽socket調用accept()時,它先到自己的receive_buf中查看是否有連接數據包;
若有,把數據拷貝出來,刪掉接收到的數據包,創建新的socket與客戶發來的地址建立連接;
若沒有,就阻塞等待;
為了在套接字中有到來的連接時得到通知,可以使用select()或poll()。當嘗試建立新連接時,系統發送一個可讀事件,然后調用accept()為該連接獲取套接字。另一種方法是,當套接字中有連接到來時設定套接字發送SIGIO信號。
返回值
成功時,返回非負整數,該整數是接收到套接字的描述符;出錯時,返回-1,相應地設定全局變量errno。
錯誤處理
Linux下,accept()把已等待的網絡錯誤傳給新建立的連接,當作是accept()返回的錯誤。這於其他的BSD實現是不同的。為了可靠運行,應該在accept()之后檢測協議已定義的一些網絡錯誤,並把這些錯誤當作EAGAIN並重試。對於TCP/IP協議來說,主要有錯誤:ENETDOWN,EPROTO,ENOPROTOOPT,EHOSTDOWN,ENONET,EHOSTUNREACH,EOPNOTSUPP和ENETUNREACH。
原文連接:http://linux.die.net/man/2/accept
