ACCEPT - Linux手册页

时间:2019-08-20 17:58:34  来源:igfitidea点击:

Linux程序员手册 第2部分
更新日期: 2020-04-11

名称

accept,accept4-接受套接字上的连接

语法

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

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

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sys/socket.h>

int accept4(int sockfd, struct sockaddr *addr,
            socklen_t *addrlen, int flags);

说明

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

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

参数addr是指向sockaddr结构的指针。如通信层所知,该结构用对等套接字的地址填充。返回的地址的确切格式由套接字的地址族确定(请参见socket(2)和相应的协议手册页)。当addr为NULL时,不填充任何内容。在这种情况下,不使用addrlen,并且也应为NULL。

addrlen参数是一个值结果参数:调用方必须对其进行初始化,以包含addr指向的结构的大小(以字节为单位);返回时,它将包含对等地址的实际大小。

如果提供的缓冲区太小,返回的地址将被截断。在这种情况下,addrlen将返回一个大于提供给调用的值。

如果队列上没有待处理的连接,并且套接字没有标记为非阻塞,则accept()会阻塞调用者,直到出现连接为止。如果套接字被标记为非阻塞并且队列上没有挂起的连接,则accept()失败,错误为EAGAIN或EWOULDBLOCK。

为了通知套接字上的传入连接,可以使用select(2),poll(2)或epoll(7)。当尝试建立新连接时,将传递一个可读事件,然后您可以调用accept()获取该连接的套接字。另外,您可以将套接字设置为在套接字上发生活动时传递SIGIO。有关详细信息,请参见socket(7)。

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

SOCK_NONBLOCK
在新文件描述符引用的打开文件描述(请参见open(2))上设置O_NONBLOCK文件状态标志。使用此标志可以节省对fcntl(2)的额外调用,以实现相同的结果。
SOCK_CLOEXEC
在新文件描述符上设置执行时关闭(FD_CLOEXEC)标志。有关为什么可能有用的原因,请参见open(2)中O_CLOEXEC标志的描述。

返回值

成功完成后,这些系统调用将为接受的套接字返回一个文件描述符(非负整数)。如果出错,则返回-1,正确设置errno,并且addrlen保持不变。

Error handling

Linux accept()(和accept4())在新套接字上传递已经挂起的网络错误,作为来自accept()的错误代码。此行为与其他BSD套接字实现不同。为了可靠运行,应用程序应在accept()之后检测为协议定义的网络错误,并通过重试将其视为EAGAIN。对于TCP / IP,它们是ENETDOWNEPROTOENOPROTOOPTEHOSTDOWNENONETEHOSTUNREACH,EOPNOTSUPP和ENETUNREACH。

错误说明

EAGAINor EWOULDBLOCK
套接字被标记为非阻塞,并且不存在任何接受的连接。 POSIX.1-2001和POSIX.1-2008允许在这种情况下返回任何一个错误,并且不需要这些常量具有相同的值,因此可移植应用程序应检查这两种可能性。
EBADF
sockfd不是打开的文件描述符。
ECONNABORTED
连接已中止。
EFAULT
addr参数不在用户地址空间的可写部分中。
EINTR
系统调用被有效连接到达之前捕获的信号中断;参见signal(7)。
EINVAL
套接字没有监听连接,或者addrlen无效(例如,为负)。
EINVAL
(accept4())标志中的无效值。
EMFILE
已达到打开文件描述符数量的每个进程限制。
ENFILE
已达到系统范围内打开文件总数的限制。
ENOBUFS, ENOMEM
可用内存不足。这通常意味着内存分配不受套接字缓冲区限制的限制,而不受系统内存的限制。
ENOTSOCK
文件描述符sockfd不引用套接字。
EOPNOTSUPP
引用的套接字不是SOCK_STREAM类型。
EPROTO
协议错误。

此外,如果满足以下条件,Linux accept()可能会失败:

EPERM
防火墙规则禁止连接。

此外,可能会返回新套接字的网络错误以及为协议定义的网络错误。各种Linux内核都可以返回其他错误,例如ENOSRESOCKTNOSUPPORTEPROTONOSUPPORT,ETIMEDOUT。在跟踪期间可能会看到值ERESTARTSYS。

版本

从Linux 2.6.28开始可以使用accept4()系统调用。从版本2.10开始,将提供glibc支持。

遵循规范

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

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

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

备注

POSIX.1-2001不需要包含,并且在Linux上不需要此头文件。但是,某些历史(BSD)实现需要此头文件,而可移植的应用程序最好将其包括在内。

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

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

The socklen_t type

在原始的BSD套接字实现中(以及在其他较旧的系统上),accept()的第三个参数被声明为int *。 POSIX.1g草案标准希望将其更改为size_t * C;后来的POSIX标准和glibc 2.x都有socklen_t *。

示例

参见bind(2)。

另外参见

绑定(2),连接(2),监听(2),选择(2),套接字(2),套接字(7)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/