accept(2)

NAZWA
accept, accept4 - przyjmuje połączenia na gnieździe

BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)

SKŁADNIA
#include <sys/socket.h>

int accept(int sockfd, struct sockaddr *_Nullable restrict addr,
           socklen_t *_Nullable restrict addrlen);

#define _GNU_SOURCE             /* zobacz feature_test_macros(7) */
#include <sys/socket.h>

int accept4(int sockfd, struct sockaddr *_Nullable restrict addr,
           socklen_t *_Nullable restrict addrlen, int flags);

OPIS
Wywołanie systemowe accept() jest używane z połączeniowymi typami gniazd (SOCK_STREAM, SOCK_SEQPACKET). Wyciąga ona pierwsze żądanie połączenia z kolejki oczekujących połączeń dla nasłuchującego gniazda sockfd, tworzy nowo podłączone gniazdo i zwraca nowy deskryptor pliku odnoszący się do tego gniazda. Nowo utworzone gniazdo nie jest już w stanie nasłuchiwania. Oryginalne gniazdo sockfd pozostaje po tym wywołaniu niezmienione.

Argument sockfd jest gniazdem, które zostało utworzone wywołaniem socket(2), przywiązanym do adresu lokalnego z pomocą bind(2), i nasłuchującym połączeń po wywołaniu listen(2).

Argument addr jest wskaźnikiem do struktury sockaddr. Do struktury tej jest wpisywany adres drugiego gniazda, przekazany przez warstwę komunikacyjną. Dokładny format zwracanego adresu addr jest określony poprzez rodzinę adresową gniazda (zobacz socket(2) i strony podręcznika dotyczące odpowiedniego protokołu). Gdy addr jest równe NULL, to nic nie jest wypełniane; w takim przypadku addrlen nie jest używane i również powinno wynosić NULL.

Argument addrlen jest parametrem wartościowo-wynikowym: powinien początkowo zawierać rozmiar (w bajtach) struktury, na którą wskazuje addr; po zakończeniu będzie zawierał rzeczywistą długość zwracanego adresu.

Zwracany adres jest przycinany, jeśli udostępniony bufor jest zbyt mały; w tym przypadku addrlen zwróci wartość większą niż była podana w wywołaniu.

Jeśli nie ma zalegających połączeń w kolejce, a gniazdo nie jest zaznaczone jako nieblokujące, to accept() blokuje proces wywołujący aż do uzyskania połączenia. Gdy gniazdo jest zaznaczone jako nieblokujące i nie ma zalegających połączeń w kolejce, accept() zawodzi z błędem EAGAIN lub EWOULDBLOCK.

Aby być informowanym o nadchodzących do gniazda połączeniach, można użyć select(2), poll(2) lub epoll(7). Podczas próby nowego połączenia zostanie dostarczone zdarzenie odczytywalności (readable) i wtedy można wywołać accept() aby uzyskać gniazdo tego połączenia. Inaczej, można ustawić gniazdo tak, by dostarczało SIGIO za każdym razem, gdy się na nim coś zacznie dziać; szczegóły można znaleźć w socket(7).

Jeśli flags wynosi 0, to accept4() jest taka sama jak accept(). Następujące wartości flags można zsumować logicznie, aby uzyskać odmienne zachowanie:

SOCK_NONBLOCK
    Ustawia znacznik statusu pliku O_NONBLOCK na otwartym deskryptorze pliku (zob. open(2) do którego odnosi się nowy deskryptor pliku. Użycie tego znacznika zapobiega dodatkowym wywołaniom do fcntl(2) przy uzyskaniu tego samego efektu.

SOCK_CLOEXEC
    Ustawia znacznik zamknięcia-przy-wykonaniu (FD_CLOEXEC) na nowym deskryptorze pliku. Opis znacznika O_CLOEXEC w podręczniku open(2) informuje o przypadkach, w których może się to okazać przydatne.

WARTOŚĆ ZWRACANA
W przypadku sukcesu, te wywołania systemowe zwracają deskryptor pliku dla zaakceptowanego gniazda (nieujemną liczbę całkowitą). W razie zaistnienia błędu, zwracane jest -1, ustawiane jest errno wskazując błąd, a addrlen nie ulega zmianie.

  Obsługa błędów
Linuksowe accept (i accept4()) przekazuje zalegające już na nowym gnieździe błędy sieciowe jako kod błędu z accept(). Zachowanie to różni się od implementacji gniazd w BSD. Dla sensownego działania, aplikacja powinna wykrywać po wykonaniu accept() błędy sieciowe, zdefiniowane dla danego protokołu i traktować je jak EAGAIN, czyli ponawiać próbę. W wypadku TCP/IP są to ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP i ENETUNREACH.

BŁĘDY

EAGAIN lub EWOULDBLOCK
    Gniazdo jest oznaczone jako nieblokujące i nie występują połączenia do zaakceptowania. POSIX.1-2001 i POSIX.1-2008 zezwalają na zwrócenie w takim przypadku dowolnego z dwóch błędów i nie wymagają, aby miały one taką samą wartość, dlatego przenośne aplikacje powinny sprawdzić oba przypadki.

EBADF
    sockfd nie jest deskryptorem otwartego pliku.

ECONNABORTED
    Połączenie zostało przerwane.

EFAULT
    Argument addr nie znajduje się w przestrzeni adresowej dostępnej do zapisu dla użytkownika.

EINTR
    Wywołanie systemowe zostało przerwane wskutek odebrania sygnału przed prawidłowym nawiązaniem połączenia; zob. signal(7).

EINVAL
    Gniazdo nie nasłuchuje połączeń lub addrlen jest nieprawidłowe (np. jest ujemne).

EINVAL
    (accept4()) nieprawidłowa wartość w flags.

EMFILE
    Zostało osiągnięte ograniczenie na liczbę otwartych deskryptorów plików dla procesu.

ENFILE
    Zostało osiągnięte systemowe ograniczenie na całkowitą liczbę otwartych plików.

ENOBUFS
ENOMEM
    Jest niedostateczna ilość wolnej pamięci. Oznacza to zazwyczaj, że istnieje ograniczenie dla przydzielania pamięci na bufory gniazd, nie zaś że zabrakło pamięci w systemie.

ENOTSOCK
    Deskryptor pliku sockfd nie odnosi się do gniazda.

EOPNOTSUPP
    Przekazane gniazdo nie jest typu SOCK_STREAM.

EPERM
    Reguły zapory sieciowej zabraniają połączenia.

EPROTO
    Wystąpił błąd protokołu.

Dodatkowo, dla nowego gniazda mogą być zwracane błędy sieciowe zdefiniowane dla danego protokołu. Różne jądra Linux mogą zwracać inne błędy, takie jak ENOSR, ESOCKTNOSUPPORT, EPROTONOSUPPORT, ETIMEDOUT. Wartość ERESTARTSYS może być obserwowana podczas śledzenia.

WERSJE
W Linuksie, nowe gniazdo zwracane przez accept() nie dziedziczy znaczników statusu pliku, takich jak O_NONBLOCK i O_ASYNC od nasłuchującego gniazda. Takie zachowanie różni się od tradycyjnej implementacji gniazd BSD. Przenośne programy nie powinny polegać na dziedziczeniu lub niedziedziczeniu znaczników statusu pliku i zawsze ustawiać wprost wszystkie wymagane znaczniki na gnieździe zwracanym przez accept(2).

STANDARDY

accept()
    POSIX.1-2008.

accept4()
    Linux.

HISTORIA

accept()
    POSIX.1-2001, SVr4, 4.4BSD (accept() pojawiło się pierwotnie w 4.2BSD).

accept4()
    Linux 2.6.28, glibc 2.10.

UWAGI
Nie zawsze po dostarczeniu SIGIO musi istnieć oczekujące połączenie. To samo dotyczy select(2), poll(2) i epoll(7), zwracających zdarzenie odczytywalności, ponieważ połączenie mogło zostać usunięte przez asynchroniczny błąd sieci lub inny wątek, przed wywołaniem accept(). Jeśli to się zdarzy, to wywołanie będzie blokować, oczekując następnego połączenia. Aby upewnić się, że accept() nigdy nie będzie blokowało, przekazane gniazdo sockfd powinno mieć ustawiony znacznik O_NONBLOCK (zobacz socket(7)).

Dla niektórych protokołów wymagających bezpośredniego potwierdzania, takich jak DECnet, accept() może być uważane za wywołanie zdejmujące z kolejki następne żądanie połączenia, nie powodując potwierdzenia. Potwierdzenie można spowodować przez normalny odczyt, lub zapis na nowym deskryptorze pliku, a odrzucenie można spowodować, zamykając gniazdo. Obecnie pod Linuksem taką semantykę ma tylko DECnet.

  Typ socklen_t
W oryginalnej implementacji gniazd BSD (i innych starszych systemów) trzeci argument accept() był deklarowany jako int *. Szkic POSIX.1g planował zmienić to na size_t *C; późniejsze standardy POSIX oraz glibc 2.x posiadają socklen_t * .

PRZYKŁADY
Zobacz bind(2).

ZOBACZ TAKŻE
bind(2), connect(2), listen(2), select(2), socket(2), socket(7)

TŁUMACZENIE
Autorami polskiego tłumaczenia niniejszej strony podręcznika są: Przemek Borys <pborys@dione.ids.pl>, Andrzej Krzysztofowicz <ankry@green.mf.pg.gda.pl> i Michał Kułach <michal.kulach@gmail.com>

Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 (https://www.gnu.org/licenses/gpl-3.0.html) lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.

Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.