linux手册翻译——accept(2)


accept, accept4 - accept a connection on a socket

#include 
int accept(int sockfd, struct sockaddr *restrict addr,
                  socklen_t *restrict addrlen);

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include 
int accept4(int sockfd, struct sockaddr *restrict addr,
                  socklen_t *restrict addrlen, int flags);


accept() 系统调用与基于连接的套接字类型(SOCK_STREAM、SOCK_SEQPACKET)一起使用。 它从侦听套接字(sockfd)的挂起连接队列上的提取第一个连接请求,创建一个新的连接套接字,并返回一个引用该套接字的新文件描述符。新创建的套接字未处于侦听状态。 原始套接字 sockfd 不受此调用的影响。

参数 sockfd 是一个使用 socket(2) 创建的套接字,使用 bind(2) 绑定到本地地址,并在 listen(2) 之后侦听连接。

参数 addr 是指向 sockaddr 结构的指针。 此结构由对等的套接字(即客户端套接字)的地址填充。 返回 addr 的地址的确切格式由套接字的地址族确定(请参阅 socket(2) 和相应的协议手册页)。 当addr为NULL时,什么都不填; 在这种情况下,不使用 addrlen,也应该是 NULL。

addrlen 参数是一个 value-result 参数:调用者必须初始化它以包含 addr 指向的结构的大小(以字节为单位); 返回时,它将包含对等地址的实际大小。如果提供的缓冲区太小,则截断返回的地址; 在这种情况下, addrlen 将返回一个大于提供给调用的值。

如果队列中没有挂起的连接,并且套接字没有被标记为非阻塞,accept() 会阻塞调用者,直到存在连接。 如果套接字被标记为非阻塞并且队列中没有挂起的连接,accept() 将失败并返回错误 EAGAIN 或 EWOULDBLOCK。

为了在套接字上收到传入连接的通知,可以使用 select(2)、poll(2) 或 epoll(7)。 当尝试新连接时,将传递一个可读事件,然后调用 accept() 以获取该连接的套接字。 或者,设置套接字以在套接字上发生活动时产生 SIGIO信号,然后在信号处理程序中进行连接; 有关详细信息,请参阅 socket(7)。

如果flags 为0,则accept4() 与accept() 相同。 以下值可以在标志中按位或进行运算以获得不同的行为:

  • SOCK_NONBLOCK
  • SOCK_CLOEXEC
    这两个参数无需多言,需要注意的是,此标志是给到新创建的fd中,而非传入的socket-fd,我们在socket(2)讲到了,可以在socket()的type中设置这两个flag。在linux中,新创建的fd并不会继承,见CONFORMING TO。


成功时,这些系统调用将返回已接受(accepted)套接字的文件描述符(非负整数)。 出错时,返回 -1,设置 errno 以指示错误,并且 addrlen 保持不变。

Error handling

Linux accept() (and accept4()) passes already-pending network errors on the new socket as an error code from accept(). This behavior differs from other BSD socket implementations. For reliable operation the application should detect the network errors defined for the protocol after accept() and treat them like EAGAIN by retrying. In the case of TCP/IP, these are ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH.

  • EAGAINEWOULDBLOCK
    套接字被标记为非阻塞并且不存在要接受的连接。 POSIX.1-2001 和 POSIX.1-2008 允许在这种情况下返回任何一个错误,并且不要求这些常量具有相同的值,因此便携式应用程序应该检查这两种可能性。

  • EBADF
    sockfd 不是一个打开的文件描述符

  • ECONNABORTED
    连接已经被终止

  • EFAULT
    addr 参数不在用户地址空间的可写部分。

  • EINTR
    系统调用被在有效连接到达之前捕获的信号中断; 见信号(7)。

  • EINVAL
    套接字未侦听连接,或 addrlen 无效(例如,为负数)。

  • EINVAL
    (accept4()) 使用了无效的flags

  • EMFILE
    到达了单个进程可打开的文件描述符上限

  • EMFILE
    到达了系统可打开的文件描述符上限

  • ENOBUFS, ENOMEM
    没有足够的可用内存。 这通常意味着内存分配受套接字缓冲区限制而不是系统内存的限制。

  • ENOTSOCK sockfd
    文件描述符并不指向一个套接字

  • EOPNOTSUPP
    套接字类型不是SOCK_STREAM

  • EPROTO
    协议错误

In addition, Linux accept() may fail if:

  • EPERM
    防火墙拒绝了连接

In addition, network errors for the new socket and as defined for the protocol may be returned. Various Linux kernels can return other errors such as ENOSR, ESOCKTNOSUPPORT, EPROTONOSUPPORT, ETIMEDOUT. The value ERESTARTSYS may be seen during a trace.


从 Linux 2.6.28 开始可以使用 accept4() 系统调用; glibc 支持从 2.10 版开始可用。


accept(): POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD (accept() 最早出现在 4.2BSD 中)。

accept4() 是一个非标准的 Linux 扩展。

在 Linux 上,accept() 返回的新套接字不会从侦听套接字中继承文件状态标志,例如 O_NONBLOCK 和 O_ASYNC。 此行为不同于规范的 BSD 套接字实现。 可移植程序不应依赖于文件状态标志的继承或非继承,并且始终在从 accept() 返回的套接字上显式设置所有必需的标志。


在发送SIGIO或select(2)、poll(2)或epoll(7)返回可读性事件后,可能并不总是有连接等待,因为在调用accept()之前,连接可能已经被异步网络错误或另一个线程删除了。如果发生这种情况,那么调用将阻塞等待下一个连接到达。为了确保accept()不会阻塞,传递的套接字sockfd需要设置O_NONBLOCK标志(参见socket(7))。

对于某些需要显式确认的协议,例如 DECnet,accept() 可以被认为只是使下一个连接请求出列,并不意味着确认。 确认可以通过对新文件描述符的正常读取或写入来暗示,而拒绝可以通过关闭新套接字来暗示。 目前,Linux 上只有 DECnet 具有这些语义。

The socklen_t type

在最初的 BSD 套接字实现中(以及在其他旧系统上),accept() 的第三个参数被声明为int *。 一个 POSIX.1g 标准草案想把它改成 size_t *; 后来的 POSIX 标准和 glibc 2.x 确定为 socklen_t * 。
In the original BSD sockets implementation (and on other older systems) the third argument of accept() was declared as an int *. A POSIX.1g draft standard wanted to change it into a size_t *C; later POSIX standards and glibc 2.x have socklen_t * .
定义:

#define __U32_TYPE      unsigned int    // in 
__STD_TYPE __U32_TYPE __socklen_t;      // in 
typedef __socklen_t socklen_t;          // in 

你可能感兴趣的:(linux手册翻译——accept(2))