位置:首页 > 其他技术 > Unix/Linux系统调用 > accept()函数 Unix/Linux

accept()函数 Unix/Linux

名称

accept - 接受连接套接字上

内容简介

#include <sys/types.h>
#include <sys/socket.h> 

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

描述说明

accept()系统调用用于基于连接的套接字类型(SOCK_STREAM,SOCK_SEQPACKET)。提取完成连接队列中的第一个连接请求,创建一个新的连接套接字,并返回一个新的文件描述符,指该套接字。新创建的套接字处于监听状态。原始套接字 sockfd 不受此调用。

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

参数addr是一个指向结构sockaddr。被填充在此结构的对等套接字的地址,作为已知的通信层。地址返回 addr 的确切格式由套接字的地址族(参见socket(2)及相应协议的手册页)。

addrlen 参数是一个值结果参数:最初它应该包含大小addr所指向的结构,在函数返回时将包含实际的长度(以字节为单位)返回的地址。当没有填写addr是NULL。

如果没有挂起的连接队列,并没有被标记为非阻塞套接字,accept() 将阻塞,直到建立连接。如果套接字被标记无阻塞,没有未完成连接队列上,accept() 失败,并出现错误EAGAIN。

为了通知传入连接在套接字上,那么可以使用select(2)或 orpoll(2)。当尝试一个新的连接,然后可以调用accept() 获取套接字,连接一个可读事件将被传递。另外,您还可以设置套接字提供SIGIO活动发生在一个socket时,详情参见socket(7)。

需要一个明确的确认,如 DECNET 对于某些协议,accept() 可以被看作是仅仅从队列中取出下一个连接请求,不意味着确认。确认可以正常的读或写上新的文件描述符,暗示和排斥反应,可通过关闭新的套接字暗示。目前只有DECNet有这样的Linux上的语义。

注意

可能并不总是等待一个连接后 SIGIO 交付 select(2) 或 poll(2) 因为连接可能已被删除,被称为异步网络错误或另一个线程 accept() 返回一个可读性事件。如果发生这种情况,那么调用将阻塞等待下一个连接到达。

为了确保 accept() 从未阻塞,通过套接字sockfd中需要有O_NONBLOCK标志设置(参见socket(7))。

返回值

如果成功,accept()返回一个非负的整数,这是一个接受套接字描述符。上的错误,则返回-1,errno设置为合适。

错误处理

Linux 的 accept() 传递已经挂起的网络错误,在新的socket accept() 错误代码。此行为不同于其他的BSD套接字实现。对于可靠运行的应用程序应该检测网络错误定义的协议后accept() ,并把它们像EAGAIN重试。在这些情况下,TCP/ IP是ENETDOWN ENOPROTOOPT EPROTO,EHOSTDOWN,ENONET,EHOSTUNREACH,EOPNOTSUPP,和ENETUNREACH的。 

错误

accept()可能失败如下:

标签 描述
EAGAINorEWOULDBLOCK The socket is marked non-blocking and no connections are present to be accepted.
EBADF The descriptor is invalid.
ECONNABORTED A connection has been aborted.
EINTR The system call was interrupted by a signal that was caught before a valid connection arrived.
EINVAL Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
EMFILE The per-process limit of open file descriptors has been reached.
ENFILE The system limit on the total number of open files has been reached.
ENOTSOCK The descriptor references a file, not a socket.
EOPNOTSUPP The referenced socket is not of typeSOCK_STREAM.

accept() 可能会失败,如下:

标签 描述
EFAULT The addr argument is not in a writable part of the user address space.
ENOBUFS, ENOMEM Not enough free memory. This often means that the memory allocation is limited by the socket bufferlimits, not by the system memory.
EPROTO Protocol error.

Linux accept() 可能会失败,如下:

标签 描述
EPERM Firewall rules forbid connection.

此外,新的套接字的协议所定义的网络错误可能被返回。各种 Linux 内核可以返回其他错误,如ENOSR ESOCKTNOSUPPORT,EPROTONOSUPPORT ETIMEDOUT。在跟踪过程中,可能会出现值ERESTARTSYS。

遵循于

SVr4, 4.4BSD (accept() first appeared in 4.2BSD).

注意

最初是作为一个'‘int *’'声明 accept()的第三个参数(libc4和libc5和许多其他系统,如4.x的BSD,SunOS 4上,SGI);下一个POSIX.1g标准草案希望改变它变成了'size_t*',那是什么它是在SunOS5。后来POSIX汇票“socklen_t*”,这样做对单一Unix规范和glibc2。

另请参阅