ACCEPT(2) Linux Programmer's Manual ACCEPT(2) NAME accept, accept4 - accept a connection on a socket /*在一个套接字上接收一个连接*/ SYNOPSIS #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); DESCRIPTION The accept() system call is used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET). It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket. The newly created socket is not in the listening state. The original socket sockfd is unaffected by this call. /*accept 函数是用于基于连接的套接字(SOCK_STREAM, SOCK_SEQPACKET)。它会选择连接等待队列中的第一个连接请求,然后创建一个新的连接套接字并且返回一个指向该套接字的文件描述符。新创建的套接字并不会处于监听状态,原来的套接字(accept 参数中的套接字描述符所指向的套接字)不会受到 accept 调用函数的影响(包括文件状态位标志等)*/ The argument sockfd is a socket that has been created with socket(2), bound to a local address with bind(2), and is listening for connections after a listen(2). /*sockfd 参数是一个套接字,该套接字由 socket 函数创建、bind 函数绑定本地地址,并且最后由 listen 函数设置用于监听连接的套接字。*/ The argument addr is a pointer to a sockaddr structure. This structure is filled in with the address of the peer socket, as known to the communications layer. The exact format of the address returned addr is determined by the socket's address family (see socket(2) and the respective protocol man pages). When addr is NULL, nothing is filled in; in this case, addrlen is not used, and should also be NULL. /*addr 参数是一个指向 sockaddr 结构体的指针。该结构体包含了对方 socket 的地址,也就是众所周知的网络层。addr 的准确格式取决于套接字的地址族(请参阅 socket(2) 和相应的协议手册页)。当 addr == NULL 时,accept 函数不会获取任何信息,这时 addrlen 参数就毫无意义了,那么最后一个参数也应该填 NULL*/ The addrlen argument is a value-result argument: the caller must initialize it to contain the size (in bytes) of the structure pointed to by addr; on return it will contain the actual size of the peer address. /*addrlen 参数是一个值结果参数:调用者必须先初始化它,该参数用于储存 addr 指向结构体的大小(以字节为单位)。函数返回时,addrlen 将会把对方地址结构体的大小一并带回*/ The returned address is truncated if the buffer provided is too small; in this case, addrlen will return a value greater than was supplied to the call. /*如果提供的缓冲区太小,那么返回的地址将会被截断;这时,addrlen 将会返回一个大于给该调用提供的值*/ If no pending connections are present on the queue, and the socket is not marked as nonblocking, accept() blocks the caller until a connection is present. If the socket is marked nonblocking and no pending connections are present on the queue, accept() fails with the error EAGAIN or EWOULDBLOCK. /*如果当前队列中没有等待的连接,并且 socket 也没有标记为非阻塞时, accept 函数将会阻塞调用者直到有连接为止。如果 socket 被标记为非阻塞并且当前队列中没有等待的连接时,那么 accept 函数将会出错,错误代码为 EAGAIN 或 EWOULDBLOCK*/ In order to be notified of incoming connections on a socket, you can use select(2) or poll(2). A readable event will be delivered when a new connection is attempted and you may then call accept() to get a socket for that connection. Alternatively, you can set the socket to deliver SIGIO when activity occurs on a socket; see socket(7) for details. /*我们可以通过调用 select 函数或者 poll 函数来知道目前加入到连接队列的套接字。当一个新的请求尝试连接,并且此时我们调用 accept 函数创建了一个 socket ,这时我们就可以实现可读事件的传递了。当然了,我们也可以对 socket 进行设置,当 socket 有变化时立即发送 SIGIO 信号。具体细节参见 socket(7)*/ For certain protocols which require an explicit confirmation, such as DECNet, accept() can be thought of as merely dequeuing the next connection request and not implying confirmation. Confirmation can be implied by a normal read or write on the new file descriptor, and rejection can be implied by closing the new socket. Currently only DECNet has these semantics on Linux. /*对于某些需要显式确认的协议,例如 DECNet,accept 函数则可以看作仅仅从队列中取出下一个连接而不做确认。当在一个新的文件描述符上进行普通读写操作时暗含了确认,当关闭这个新的套接字时暗含了拒绝。目前在 Linux 上只有 DECNet 具有这些含义*/ If flags is 0, then accept4() is the same as accept(). The following values can be bitwise ORed in flags to obtain different behavior: /*如果 flag 参数为 0,则 accept4 函数和 accept 函数一样。以下值可以在标志中按位或运算以获得不同的行为。*/ SOCK_NONBLOCK Set the O_NONBLOCK file status flag on the new open file description. Using this flag saves extra calls to fcntl(2) to achieve the same result. /*SOCK_NONBLOCK 在新的打开文件描述中设置 O_NONBLOCK(非阻塞)文件状态标志.使用此标志可以节省对 fcntl 的额外调用,以实现相同的结果*/ SOCK_CLOEXEC Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor. See the description of the O_CLOEXEC flag in open(2) for reasons why this may be useful. /*SOCK_CLOEXEC 在新的打开文件描述中设置 close-on-exec (FD_CLOEXEC)文件状态标志.请参阅open 函数中 O_CLOEXEC 标志的说明了解设置该状态标志位的用处。*/ RETURN VALUE On success, these system calls return a nonnegative integer that is a descriptor for the accepted socket. On error, -1 is returned, and errno is set appropriately. /*成功,这些系统调用会返回一个非负整数,它是接受套接字的描述符;失败返回 -1,错误代码保存在 errno 中*/ Error handling Linux accept() (and accept4()) passes already-pending network errors on the new socket as an error code from accept(). This behavior differs from other BSD socket implementations. For reliable operation the application should detect the network errors defined for the protocol after accept() and treat them like EAGAIN by retrying. In the case of TCP/IP, these are ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH. /*Linux accept(and accept4) 的错误处理是通过双方所连接的网络上的新的套接字实现的,该套接字所传递的错误信息仅仅只是 accept 函数出错所产生的错误代码,也就是 errno 的值,该方法与其他 BSD 套接字的实现有所不同。为了实现可靠的操作,应用程序应该在 accept 函数之后检测由于协议定义所产生的网络错误,并可以像 EAGAIN 一样通过重试对待。在 TCP/IP 情况下包括: ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH*/ ERRORS EAGAIN or EWOULDBLOCK The socket is marked nonblocking and no connections are present to be accepted. POSIX.1-2001 and POSIX.1-2008 allow either error to be returned for this case, and do not require these constants to have the same value, so a portable application should check for both possibilities. /*EAGAIN or EWOULDBLOCK 套接字被标记为非阻塞,同时并不存在要接受的连接。POSIX.1-2001 和 POSIX.1-2008 允许为这种情况返回错误,并且不要求这些常量具有相同的值,因此可移植的应用程序应该检查两种可能性*/ EBADF The descriptor is invalid. /*EBADF 描述符无效*/ ECONNABORTED A connection has been aborted. /*ECONNABORTED 连接已终止*/ EFAULT The addr argument is not in a writable part of the user address space. /*EFAULT addr 参数不是用户地址空间的可写部分*/ EINTR The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7). /*EINTR 系统调用被一个在有效连接到达之前捕获的信号中断*/ EINVAL Socket is not listening for connections, or addrlen is invalid(e.g., is negative). /*EINVAL socket 并不是监听套接字,或者 addrlen 是无效的(例如,addrlen 是负值)*/ EINVAL (accept4()) invalid value in flags. /*EINVAL accept4 函数无效的标志位设置*/ EMFILE The per-process limit on the number of open file descriptors has been reached. /*EMFILE 已达每个进程所能打开的文件描述符上限*/ ENFILE The system-wide limit on the total number of open files has been reached. /*ENFILE 已达到系统范围内打开文件总数的上限*/ ENOBUFS, ENOMEM Not enough free memory. This often means that the memory allocation is limited by the socket buffer limits, not by the system memory. /*ENOBUFS, ENOMEM 内存不足。这个错误一般来说意味着内存分配受套接字缓冲区所限, 而不是没有系统内存*/ ENOTSOCK The file descriptor sockfd does not refer to a socket. /*ENOTSOCK sockfd 参数不是一个套接字*/ EOPNOTSUPP The referenced socket is not of type SOCK_STREAM. /*EOPNOTSUPP 引用的套接字不是 SOCK_STREAM 类型*/ EPROTO Protocol error. /*EPROTO 协议错误*/ In addition, Linux accept() may fail if: /*此外,如果出现以下情况,Linux accept 函数也会出错*/ EPERM Firewall rules forbid connection. /*EPERM 防护墙设置禁止连接*/ In addition, network errors for the new socket and as defined for the protocol may be returned. Various Linux kernels can return other errors such as ENOSR, ESOCKTNOSUPPORT, EPROTONOSUPPORT, ETIMEDOUT. The value ERESTARTSYS may be seen during a trace. /*此外,新套接字的网络错误以及协议中定义的错误也会被返回。不同的 Linux 内核也会返回一些其他问题,如:ENOSR, ESOCKTNOSUPPORT, EPROTONOSUPPORT, ETIMEDOUT。一直追溯可以看到 ERESTARTSYS 的值*/ VERSIONS The accept4() system call is available starting with Linux 2.6.28; support in glibc is available starting with version 2.10. /*accept4 系统调用函数从 Linux 2.6.28 版本才开始使用的;glibc 支持版本是从 2.10 开始提供*/ CONFORMING TO accept(): POSIX.1-2001, POSIX.1-2008, SVr4, 4.4BSD (accept() first appeared in 4.2BSD). /*accept 函数第一次出现是在 4.2BSD 中*/ accept4() is a nonstandard Linux extension. /*accept4 函数是一个非标准的 Linux 扩展*/ On Linux, the new socket returned by accept() does not inherit file status flags such as O_NONBLOCK and O_ASYNC from the listening socket. This behavior differs from the canonical BSD sockets implementation. Portable programs should not rely on inheritance or noninheritance of file status flags and always explicitly set all required flags on the socket returned from accept(). /*在 Linux 上,accept 函数返回的新套接字不会从监听套接字中继承文件状态标志,例如:O_NONBLOCK 和 O_ASYNC。这和规范的 BSD 套接字实现机制有所不同。可移植程序不应该依赖于文件状态的是否可继承,而是应当在 accept 函数返回时就将所有需求都在 socket 的相应标志位上设置好。 可移植程序不应该依赖于文件状态标志的继承或不继承,并且总是显式地设置从accept()返回的套接字上所有必需的标志。*/ NOTES POSIX.1-2001 does not require the inclusion of <sys/types.h>, and this header file is not required on Linux. However, some historical (BSD) implementations required this header file, and portable applications are probably wise to include it. /*POSIX.1 不需要 <sys/types.h>头文件,但是由于历史原因(例如:BSD)就需要该头文件,所有还是加一下该头文件比较好*/ There may not always be a connection waiting after a SIGIO is delivered or select(2) or poll(2) return a readability event because the connection might have been removed by an asynchronous network error or another thread before accept() is called. If this happens, then the call will block waiting for the next connection to arrive. To ensure that accept() never blocks, the passed socket sockfd needs to have the O_NONBLOCK flag set (see socket(7)). /*当接收到一个 SIGIO 信号或者 select、poll 函数返回读就绪时并不总是意味着有新的连接在等待,因为连接很可能在 accept 函数调用之前被一个异步网络错误或者另一个线程删除。如果发生这种情况, 那么调用将阻塞并等待下一个连接的到来。为确保 accept 永远不会阻塞,传递的套接字 sockfd 需要设置成 O_NONBLOCK 标志(参见 socket(7))*/ The socklen_t type /*socklen_t 类型*/ The third argument of accept() was originally declared as an int * (and is that under libc4 and libc5 and on many other systems like 4.x BSD, SunOS 4, SGI); a POSIX.1g draft standard wanted to change it into a size_t *, and that is what it is for SunOS 5. Later POSIX drafts have socklen_t *, and so do the Single UNIX Specification and glibc2. Quoting Linus Torvalds: /*函数 accept 的第三个参数原来被声明为 int * (在libc4 和 libc5 以及其他很多系统中, 比如 BSD 4.x, SunOS 4, SGI); POSIX.1g 草案试图将其改变为 size_t * 类型, SunOS 5 是这么做的。 后来的POSIX 草案和 Single Unix Specification 以及 glibc2 使用了 socklen_t *。引用 Linus Torvalds 一段话:*/ "_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 说这是由于他们发现了自己的错误但又不好意思向大家伙儿承认,所以另外创造了一个新的数据类型。*/ EXAMPLE See bind(2). SEE ALSO bind(2), connect(2), listen(2), select(2), socket(2), socket(7) COLOPHON This page is part of release 4.04 of the Linux man-pages project. A description of the project, information about reporting bugs, and the latest version of this page, can be found at http://www.kernel.org/doc/man-pages/. Linux 2015-12-28 ACCEPT(2)
accept 翻译
猜你喜欢
转载自blog.csdn.net/wenfei11471/article/details/80084259
今日推荐
周排行