ACCEPT - Linux手册页
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()相同。可以对标志中的以下值进行按位或运算以获得不同的行为:
返回值
成功完成后,这些系统调用将为接受的套接字返回一个文件描述符(非负整数)。如果出错,则返回-1,正确设置errno,并且addrlen保持不变。
Error handling
Linux accept()(和accept4())在新套接字上传递已经挂起的网络错误,作为来自accept()的错误代码。此行为与其他BSD套接字实现不同。为了可靠运行,应用程序应在accept()之后检测为协议定义的网络错误,并通过重试将其视为EAGAIN。对于TCP / IP,它们是ENETDOWN,EPROTO,ENOPROTOOPT,EHOSTDOWN,ENONET,EHOSTUNREACH,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内核都可以返回其他错误,例如ENOSR,ESOCKTNOSUPPORT,EPROTONOSUPPORT,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/。