Linux 2.2 Page
7 May 1999
Aliases: accept4(2), accept4(2), accept4(2), accept4(2), accept4(2), accept4(2), accept4(2), accept4(2), accept4(2), accept4(2)
manpages-zh
Chinese manual pages
man-pages-zh-CN
Chinese Man Pages from Chinese Man Pages Project
man-pages-zh_cn
Simplified Chinese Linux man pages
manpages-dev
Manual pages about using GNU/Linux for development
man-pages
Linux kernel and C library user-space interface documentation
NAME 名称
accept - 在一个套接字上接收一个连接
SYNOPSIS 概述
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
DESCRIPTION 描述
accept 函数用于基于连接的套接字 (SOCK_STREAM, SOCK_SEQPACKET 和 SOCK_RDM). 它从未完成连接队列中取出第一个连接请求,创建一个和参数 s 属性相同的连接套接字,并为这个套接字分配一个文件描述符, 然后以这个描述符返回.新创建的描述符不再处于倾听状态.原 套接字 s 不受此调用的影响.注意任意一个文件描述符标志 (任何可以被 fcntl以参数 F_SETFL 设置的值,比如非阻塞式或者异步状态)不会被 accept. 所继承.
参数 s 是以 socket(2) 创建,用 bind(2) 绑定到一个本地地址,并且在调用了 listen(2). 之后正在侦听一个连接的套接字. 参数 addr 是一个指向结构sockaddr的指针.这个结构体以连接实体地址填充. 所谓的连接实体,就是众所周知的网络层.参数 addr 所传递的真正的地址格式依赖于所使用的套接字族. (参见 socket(2) 和各协议自己的手册页). addrlen 是一个实时参数: 它的大小应该能够足以容纳参数 addr 所指向的结构体;在函数返回时此参数将以字节数表示出返回地址的 实际长度.若 addr 使用NULL作为参数,addrlen将也被置为NULL.
如果队列中没有未完成连接套接字,并且套接字没有标记为非阻塞式, accept 将阻塞直到一个连接到达.如果一个套接字被标记为非阻塞式而队列 中没有未完成连接套接字, accept 将返回EAGAIN.
使用 select(2) 或者 poll(2). 可以在一个套接字上有连接到来时产生事件.当尝试一个新的连接时 套接字读就绪,这样我们就可以调用 accept 为这个连接获得一个新的套接字.此外,你还可以设置套接字在唤醒时 接收到信号 SIGIO; 细节请参见 socket(7)
对于那些需要显式确认的协议,比如 DECNet, accept 可以看作仅仅从队列中取出下一个连接而不做确认.当在这个新的文件 描述符上进行普通读写操作时暗示了确认,当关闭这个新的套接字时暗 示了拒绝.目前在Linux上只有DECNet有这样 的含义.
NOTES 注意
RETURN VALUE 返回值
此调用在发生错误时返回-1.若成功则返回一个非负整数标识这个 连接套接字.
ERROR HANDLING 错误处理
Linux accept 将一个待处理网络错误代码通过 accept 传递给新套接字 . 这种处理方式有别于其他的BSD套接字实现.为可靠操作,应用程序 必须在调用 accept 之后能够检测这些为协议定义的网络错误,并且以重试解决,就象 EAGAIN 一样.对于TCP/IP这些网络错误是 ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, 以及 ENETUNREACH.
ERRORS 错误
EAGAIN或者EWOULDBLOCK | |
套接字被标记为非阻塞,且当前没有可接收的连接. | |
EBADF | 描述符非法. |
ENOTSOCK | |
描述符指向一个文件,而不是一个套接字. | |
EOPNOTSUPP | |
作为参数的套接字不是 SOCK_STREAM. 类型 | |
EFAULT | 参数 addr 不在用户可写地址空间之内. |
EPERM | 防火墙规则禁止连接. |
ENOBUFS,ENOMEM | |
没有足够内存. 这个错误一般来说意味着内存分配受套接字缓冲区所限, 而不是没有系统内存. |
CONFORMING TO 兼容于
SVr4,4.4BSD( accept 函数首次出现于BSD 4.2). BSD手册页文档定义了五个可能的错误返回值 (EBADF, ENOTSOCK, EOPNOTSUPP, EWOULDBLOCK, EFAULT). SUSv2文档的定义是EAGAIN, EBADF, ECONNABORTED, EFAULT, EINTR, EINVAL, EMFILE, ENFILE, ENOBUFS, ENOMEM, ENOSR, ENOTSOCK, EOPNOTSUPP, EPROTO, EWOULDBLOCK.
Linux accept不继承象 O_NONBLOCK 这样的套接字标志. 这一点有别于其他的BSD套接字实现. 因此,程序应该在accept所返回的套接字上设置所有需要的标志.
NOTE 注意
函数 accept 的第三个参数原来被声明为’int *’(在libc4和libc5以及其他很多系统中, 比如BSD 4.*,SunOS 4, SGI);POSIX 1003.1g草案试图将其改变为 ‘size_t *’,SunOS 5就是这么做的. 后来的POSIX草案和Single Unix Specification以及glibc2使用了 ‘socklen_t *’. Quoting Linus Torvalds: 引自Linus Torvalds (译注:这个家伙就是Linux的创始人,所以我保留了他老人家的原文, 仅将原文大意附后): I fails: only italicizes a single line _Any_ sane library _must_ have "socklen_t" be the same size as int. Anything else breaks any BSD socket layer stuff. POSIX initially _did_ make it a size_t, and I (and hopefully others, but obviously not too many) complained to them very loudly indeed. Making it a size_t is completely broken, exactly because size_t very seldom is the same size as "int" on 64-bit architectures, for example. And it _has_ to be the same size as "int" because that’s what the BSD socket interface is. Anyway, the POSIX people eventually got a clue, and created "socklen_t". They shouldn’t have touched it in the first place, but once they did they felt it had to have a named type for some unfathomable reason (probably somebody didn’t like losing face over having done the original stupid thing, so they silently just renamed their blunder).
数据类型"socklen_t"和int应该具有相同的长度.否则就会破坏 BSD套接字层的填充.POSIX开始的时候用的是size_t, Linus Torvalds(他希望有更多的人,但显然不是很多) 努力向他们解释使用size_t是完全错误的,因为在64位结构中 size_t和int的长度是不一样的,而这个参数(也就是accept函数 的第三参数)的长度必须和int一致,因为这是BSD套接字接口 标准.最终POSIX的那帮家伙找到了解决的办法,那就是创造了 一个新的类型"socklen_t".Linux Torvalds说这是由于他们 发现了自己的错误但又不好意思向大家伙儿承认,所以另外 创造了一个新的数据类型.
SEE ALSO 参见
[中文版维护人]
byeyear <love_my_love >
[中文版最新更新]
2002.01.27
《中国linux论坛man手册页翻译计划》:
http://cmpp.linuxforum.net
跋
本页面中文版由中文 man 手册页计划提供。
中文 man 手册页计划:https://github.com/man-pages-zh/manpages-zh
中文 man 手册页计划:https://github.com/man-pages-zh/manpages-zh
REFERENCED BY
sctp(7), bind(2), connect(2), getpeername(2), getsockname(2), getsockopt(2), listen(2), recv(2), select(2), select_tut(2), socket(2), socketcall(2), getaddrinfo(3), gethostbyname(3), getnameinfo(3), capabilities(7), ddp(7), ip(7), signal(7), sock_diag(7), socket(7), tcp(7), unix(7), socket-event(7), lpd(8), send(2), socket(1), msocket(2viewos)