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。