前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Linux】accept(2) - Linux man page

【Linux】accept(2) - Linux man page

作者头像
阿东
发布2023-07-21 14:16:16
2050
发布2023-07-21 14:16:16
举报

原文网址

accept(2): accept connection on socket - Linux man page (die.net)

Name

accept, accept4 - accept a connection on a socket

accept, accept4 - 接受套接字上的连接

Synopsis

#include [sys/types.h](https://linux.die.net/include/sys/types.h) / See NOTES /#include [sys/socket.h](https://linux.die.net/include/sys/socket.h)int accept(int

sockfd, struct sockaddr addr, socklen_t addrlen);#define _GNU_SOURCE

代码语言:txt
复制
        /* See **[feature_test_macros](https://linux.die.net/man/7/feature_test_macros)**(7) */#include <[sys/socket.h](https://linux.die.net/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_STREAMSOCK_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_STREAMSOCK_SEQPACKET)。它从监听套接字 sockfd 的待处理连接队列中提取第一个连接请求,创建一个新的连接套接字,并返回一个指向该套接字的新文件描述符。新创建的套接字不处于监听状态。原始套接字 sockfd 不受此调用影响。

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结构的指针。这个结构被填入通信层所知道的对等套接字的地址。返回的addr地址的具体格式由套接字的地址系列决定

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 指向的结构的大小(字节),返回时,它将包含对等地址的实际大小。当 addr 为NULL时,将不填写任何内容;在这种情况下 addrlen 将不被使用并且也应为NULL。

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.

如果队列中没有待处理的连接,并且套接字没有标记为非阻塞,accept()将阻塞调用者,直到出现连接。

如果套接字被标记为非阻塞,并且队列中没有挂起的连接,accept()将失败,错误信息为EAGAINEWOULDBLOCK

这里的效果在Java 中实现就是设置 ServerSocket 设置 timeout,这样 accept 的时候将会在超时之后直接返回实现非阻塞效果。

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 方法获取一个套接字连接。也可以使用套接字上面设置出现活动的时候发送SIGIO

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:

如果 flags = 0,accept4 和 accpet 方法一致,下面的值可以在 flags 中进行比特OR,以获得不同的行为。

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.

在新打开的文件描述上设置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.

在新的文件描述符上设置执行时关闭 (FD_CLOEXEC) 标志。请参阅 *open(2) 中对 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 ENETDOWNEPROTOENOPROTOOPTEHOSTDOWNENONETEHOSTUNREACHEOPNOTSUPP, and ENETUNREACH.

Linux accept()(和accept4())将新套接字上已经存在的网络错误作为accept()的错误代码传递。

这种行为与其他BSD套接字实现不同。为了保证可靠运行,应用程序应该在accept()之后检测协议定义的网络错误,并通过重试将它们像EAGAIN一样处理。

相对应的,在TCP/IP中,它们是ENETDOWNEPROTOENOPROTOOPTEHOSTDOWNENONETEHOSTUNREACHEOPNOTSUPPENETUNREACH

Errors

EAGAIN or EWOULDBLOCK

The socket is marked nonblocking and no connections are present to be accepted. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.

套接字被标记为非阻塞,并且没有连接被接受。POSIX.1-2001允许在这种情况下返回任何一种错误,并且不要求这些常量具有相同的值,因此可移植的应用程序应该检查这两种可能性。

EBADF

The descriptor is invalid.

描述符无效。

ECONNABORTED

A connection has been aborted.

连接已中止。

EFAULT

The addr argument is not in a writable part of the user address space.

参数 addr 不在用户地址空间的可写部分。

EINTR

The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).

系统调用被一个信号中断,该信号在有效连接到来之前被捕获;

EINVAL

Socket is not listening for connections, or addrlen is invalid (e.g., is negative).

Socket未监听连接,或者addrlen无效(例如,为负值)。

EINVAL

(accept4()) invalid value in flags.

(accept4()) flags 中的无效值。

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.

已达到系统对打开文件总数的限制。

ENOBUFSENOMEM

Not enough free memory. This often means that the memory allocation is limited by the socket buffer limits, not by the system memory.

可用内存不足。这通常意味着内存分配受到套接字缓冲区的限制,而不是系统内存的限制。

ENOTSOCK

The descriptor references a file, not a socket.

描述符是一个文件而不是一个Socket

EOPNOTSUPP

The referenced socket is not of type SOCK_STREAM.

引用的套接字不属于SOCK_STREAM类型。

EPROTO

Protocol error.

协议错误

In addition, Linux accept() may fail if:

此外,如果出现以下情况,Linux accept()可能会失败:

EPERM

Firewall rules forbid connection.

防火墙规则禁止连接。

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 ENOSRESOCKTNOSUPPORTEPROTONOSUPPORTETIMEDOUT. The value ERESTARTSYS may be seen during a trace.

此外,还可能返回新套接字和协议定义的网络错误。

各种Linux内核可能会返回其他错误,如ENOSRESOCKTNOSUPPORTEPROTONOSUPPORTETIMEDOUT。在跟踪过程中可能会看到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, SVr4, 4.4BSD, (accept() first appeared in 4.2BSD).

accept4() is a nonstandard Linux extension.

accept(): POSIX.1-2001,SVr4,4.4BSD,(accept()首次出现在4.2BSD中)。

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_NONBLOCKO_ASYNC。这种行为与典型的BSD套接字实现不同。可移植程序不应该依赖于文件状态标志的继承或非继承,而应该总是显式地在accept()返回的套接字上设置所有需要的标志。

Notes

POSIX.1-2001 does not require the inclusion of [sys/types.h](https://linux.die.net/include/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-2001不要求包含 <sys/types.h>,Linux上也不需要这个头文件。然而,一些历史上的(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(2)poll(2) 返回一个可读事件后,可能并不总是有连接在等待,因为在accept()被调用之前,连接可能已经被异步网络错误或其他线程移除。

如果出现这种情况,调用将阻塞,等待下一个连接的到来。为了确保accept()不会阻塞,传递的socket sockfd 的时候需要设置O_NONBLOCK标志(参见socket(7))。

The socklen_t type

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以及许多其他系统,如4.x BSD、SunOS 4、SGI上也是如此);

POSIX.1g标准草案希望将其改为 size_t * ,在SunOS 5上也是如此。

后来的POSIX草案使用了 socklen_t * , Single UNIX Specification和glibc2也是如此。

引用Linus Torvalds的话:

"Any sane library must have "socklent" be the same size as int. Anything else breaks any BSD socket layer stuff. POSIX initially _did make it a sizet, 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)."

任何正常的库都必须使 "socklent "与int大小相同。否则会破坏任何BSD套接字层的东西。POSIX最初确实使它成为一个size_t,我(希望还有其他人,但显然不是很多)确实非常大声地向他们抱怨。把它做成size_t是完全错误的,因为size_t很少和64位架构上的 "int "一样大。 "socklen_t " 必须与 "int "大小相同,因为BSD套接字接口就是这样的。

总之,POSIX的人最终找到了头绪,并创建了 "socklen_t"。他们一开始就不应该碰它,但是一旦他们碰了,他们就觉得它必须有一个命名的类型,因为某些深不可测的原因(可能有人不喜欢因为做了最初的蠢事而丢面子,所以他们默默地重新命名了他们的错误)。

Example 案例

See bind(2).

See Also

bind(2)connect(2)listen(2)select(2)socket(2)socket(7)

Referenced By

capabilities(7), ddp(7), explain(1), explain(3), explain_accept(3), explain_accept_or_die(3), getaddrinfo(3), gethostbyname(3), getnameinfo(3), getpeername(2), getsockname(2), ip(7), perlfunc(1), pth(3), recv(2), sctp(7), select_tut(2), send(2), setsockopt(2), socketcall(2), tcp(7), unix(7)

本文系外文翻译,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系外文翻译前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 原文网址
  • Name
  • Synopsis
  • Description
  • Return Value 返回结果
    • Error handling 错误处理
    • Errors
    • Versions 版本支持
    • Conforming to
    • Notes
      • The socklen_t type
      • Example 案例
      • See Also
      • Referenced By
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档