动态

详情 返回 返回

【Linux】accept(2) - Linux man page - 动态 详情

原文網址

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> / See NOTES /#include <sys/socket.h>int accept(int

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

        /* 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>_, 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 "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,我(希望還有其他人,但顯然不是很多)確實非常大聲地向他們抱怨。把它做成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)

user avatar u_13529088 头像 chuanghongdengdeqingwa_eoxet2 头像 boxuegu 头像 gvison 头像 dreamlu 头像 mecode 头像 ligaai 头像 jieduanxingdebugger 头像 lvxingdefanka 头像 andy_shawshank 头像 zhaoyun_blog 头像
点赞 11 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.