- 英文小册原文地址: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。
如果accept()返回成功,其返回值是由内核生成的一个全新的描述符,代表与所返回客户端的TCP连接。accept()的第一个参数成为监听套接字,称返回值为已连接套接字。区分两个套接字很重要,一个服务器通常在其生命周期内创建一个监听套接字。由 accept() 返回的 socket descriptor 是如假包换的 socket descriptor,开启并和远程主机建立连接,如果你要断开和 client 的连接,必须使用 close()。
返回值
accept() 返回新连接的 socket descriptor,发生异常时返回 -1,并将 errno 设置为合适的值。
例子
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!
参阅
socket(), getaddrinfo(), listen(), struct sockaddr_in
标签:listen,addr,ai,accept,手册,descriptor,man,socket From: https://blog.51cto.com/u_13887950/5806586