accept(2)
๐ accept(2) โ the "omg someone's calling, pick up bestie" syscall ๐
okay so picture this: accept, accept4 โ two little icons from the System Calls Manual who literally just answer the phone for your sockets. no cap. let's get into it ๐
๐ธ NAME ๐ธ
accept, accept4 โ bestie, it accepts a connection on a socket. that's the whole vibe.
๐ LIBRARY ๐
Standard C library โ that's libc, -lc. your girl is built in, no extra packages needed, periodt โจ
โจ SYNOPSIS โจ
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *_Nullable restrict addr,
socklen_t *_Nullable restrict addrlen);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sys/socket.h>
int accept4(int sockfd, struct sockaddr *_Nullable restrict addr,
socklen_t *_Nullable restrict addrlen, int flags);
๐ DESCRIPTION ๐
okay so accept() is a system call that only really fw connection-based socket types โ that's SOCK_STREAM and SOCK_SEQPACKET. the way it works is SO satisfying: it reaches into the queue of pending connections on your listening socket, sockfd, grabs the very first connection request, and โ ta-da ๐ฆ โ it creates a brand new connected socket and hands you back a fresh file descriptor for it.
the new socket is not in the listening state though. important. and the original sockfd? completely unaffected, she's fine, she's thriving, she's still listening bestie ๐
so sockfd has to be a socket that you already:
- made with
socket(2) - bound to a local address with
bind(2) - and put into listening mode with
listen(2)
then the addr argument โ it's a pointer to a sockaddr structure, and this thing gets filled in with the address of the peer socket, as known to the communications layer. the exact format of the returned addr depends on the socket's address family (peep socket(2) and the respective protocol man pages for that). oh and when addr is NULL? nothing gets filled in, and in that case addrlen isn't used either, so it should also be NULL. slay, consistent ๐ซถ
now addrlen is a value-result argument โ meaning it goes both ways, it's giving main character energy:
- you initialize it to the size (in bytes) of the structure that
addrpoints to - on return it holds the actual size of the peer address
heads up tho: if the buffer you provided is too small, the returned address gets truncated ๐ญ and in that case addrlen comes back with a value greater than what you passed in. so like, you can tell you got clipped.
if there are no pending connections on the queue and the socket is not marked nonblocking, accept() blocks the caller until a connection shows up. it just sits there waiting. respectfully. but if the socket is marked nonblocking and there's nothing on the queue, accept() fails with EAGAIN or EWOULDBLOCK.
and to get notified when connections come in, you can use select(2), poll(2), or epoll(7). when a new connection is attempted, a readable event gets delivered, and then you call accept() to actually get the socket for that connection. alternatively you can set the socket to deliver SIGIO when activity happens on a socket โ see socket(7) for the deets ๐
๐ง the flags situation (aka accept4's whole thing) ๐ง
if flags is 0, then accept4() is literally just accept(). same girl, different name ๐
but you can bitwise OR these values into flags for different behavior:
SOCK_NONBLOCKโ sets theO_NONBLOCKfile status flag on the open file description (seeopen(2)) that the new file descriptor refers to. using this flag saves you extra calls tofcntl(2)to get the same result. efficient queen โจSOCK_CLOEXECโ sets the close-on-exec (FD_CLOEXEC) flag on the new file descriptor. peep the description of theO_CLOEXECflag inopen(2)for why this might be useful ๐
๐ RETURN VALUE ๐
on success, these system calls return a file descriptor for the accepted socket โ a nonnegative integer ๐ฅณ
on error: -1 is returned, errno is set to indicate the error, and addrlen is left unchanged. sad but honest ๐
๐ญ Error handling ๐ญ
okay this one's a big deal so listen up bestie. Linux accept() (and accept4()) passes already-pending network errors on the new socket as an error code from accept(). this behavior is different from other BSD socket implementations, so no cap, it's a Linux thing.
for reliable operation, your 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, those errors are:
ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP, and ENETUNREACH
write those down, they WILL come up ๐ฅ
๐ ERRORS ๐
EAGAINorEWOULDBLOCKโ 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 they do not require these constants to have the same value, so a portable application should check for both possibilities. (yes both. don't be cute about it.)EBADFโsockfdis not an open file descriptor.ECONNABORTEDโ a connection has been aborted. rip ๐ชฆEFAULTโ theaddrargument is not in a writable part of the user address space.EINTRโ the system call was interrupted by a signal that was caught before a valid connection arrived. seesignal(7).EINVALโ socket is not listening for connections, oraddrlenis invalid (e.g., is negative).EINVAL(accept4()) โ invalid value inflags.EMFILEโ the per-process limit on the number of open file descriptors has been reached. too many open files bestie, close some ๐ญENFILEโ the system-wide limit on the total number of open files has been reached.ENOBUFS,ENOMEMโ not enough free memory. this often means the memory allocation is limited by the socket buffer limits, not by the system memory. important distinction โจENOTSOCKโ the file descriptorsockfddoes not refer to a socket.EOPNOTSUPPโ the referenced socket is not of typeSOCK_STREAM.EPERMโ firewall rules forbid connection. ๐ฎโ๏ธEPROTOโ protocol error.
and 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. and the value ERESTARTSYS may be seen during a trace. iykyk ๐
๐ VERSIONS ๐
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. so portable programs should not rely on inheritance or noninheritance of file status flags and should always explicitly set all required flags on the socket returned from accept(). just set them yourself, it's safer, periodt ๐
๐ STANDARDS ๐
POSIX.1-2024. certified, official, we love to see it ๐
๐ HISTORY ๐
accept()โPOSIX.1-2001,SVr4,4.4BSD(accept()first appeared in4.2BSD).accept4()โPOSIX.1-2024.Linux 2.6.28,glibc 2.10.
an icon with a long lineage fr fr ๐ฆ
๐ NOTES ๐
bestie. there may not always be a connection waiting after a SIGIO is delivered, or after select(2), poll(2), or epoll(7) return a readability event โ because the connection might have been removed by an asynchronous network error or by another thread before accept() was even called. if that happens, the call will block waiting for the next connection to arrive. not ideal!!
to ensure that accept() never blocks, the passed socket sockfd needs to have the O_NONBLOCK flag set (see socket(7)). do it. set the flag. ๐
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. niche but iconic ๐ง
๐งต The socklen_t type ๐งต
in the original BSD sockets implementation (and on other older systems) the third argument of accept() was declared as an int *.
a POSIX.1g draft standard wanted to change it into a size_t *.
later POSIX standards and glibc 2.x have socklen_t *. glow up complete โจ
๐ EXAMPLES ๐
see bind(2). that's it, that's the example. go look ๐
๐ SEE ALSO ๐
bind(2), connect(2), listen(2), select(2), socket(2), socket(7)
and that's the whole page bestie!! this came to you courtesy of Linux man-pages 6.20, dated 2025-10-29 ๐ go forth and accept() some connections, you got this ๐ซถโจ๐
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: BSD-4-Clause-UC
- Copyright 1983-1991, The Regents of the University of California
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms