- 英文小冊原文位址:beej.us/guide/bgnet…
- 作者:Beej
- 中文翻譯位址:www.chanmufeng.com/posts/netwo…
接受偵聽套接字上傳入的連接配接。
函數原型
#include <sys/types.h>
#include <sys/socket.h>
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
說明
一旦你拿到了 SOCK_STREAM 類型的socket, 并将 socket 設定好可以用來監聽( listen()) 進入的連接配接,然後你就能調用 accept() 獲得一個新的 socket descriptor,便于與後續新連接配接 client 的通信。
原本被監聽的socket仍然會被保留,當有新的連接配接進來時,通過調用accept()擷取這個新連接配接。主要的參數如下所示:
- s:listen()中的socket descriptor。
- addr:這裡寫入連接配接到你這裡的client的位址。
- addrlen:這裡會填入addr參數中傳回的資料的大小。假設你得到了一個structsockaddr_in,你可以安全地忽略它,因為這是你為addr傳入的類型。
accept() 通常會阻塞,而你可以使用 select() 事先取得 listen 中的 socket descriptor 狀态,檢查 socket 是否已經可讀(ready to read)。若已經可讀,則表示有新的連接配接正在等待被 accept()!另一個方式是将 listen 中的 socket 使用 fcntl() 設定 O_NONBLOCK 選項,然後 listen 中的 socket descriptor 就不會造成 block,而是傳回 -1,并将 errno 設定為 EWOULDBLOCK。
傳回值
例子
struct sockaddr_storage their_addr;
socklen_t addr_size;
struct addrinfo hints, *res;
int sockfd, new_fd;
// first, load up address structs with getaddrinfo():
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
getaddrinfo(NULL, MYPORT, &hints, &res);
// make a socket, bind it, and listen on it:
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(sockfd, res->ai_addr, res->ai_addrlen);
listen(sockfd, BACKLOG);
// now accept an incoming connection:
addr_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size);
// ready to communicate on socket descriptor new_fd!