Scroll to navigation

accept(2) System Calls Manual 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:

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.
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

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.
sockfd nie jest deskryptorem otwartego pliku.
Połączenie zostało przerwane.
Argument addr nie znajduje się w przestrzeni adresowej dostępnej do zapisu dla użytkownika.
Wywołanie systemowe zostało przerwane wskutek odebrania sygnału przed prawidłowym nawiązaniem połączenia; zob. signal(7).
Gniazdo nie nasłuchuje połączeń lub addrlen jest nieprawidłowe (np. jest ujemne).
(accept4()) nieprawidłowa wartość w flags.
Zostało osiągnięte ograniczenie na liczbę otwartych deskryptorów plików dla procesu.
Zostało osiągnięte systemowe ograniczenie na całkowitą liczbę otwartych plików.
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.
Deskryptor pliku sockfd nie odnosi się do gniazda.
Przekazane gniazdo nie jest typu SOCK_STREAM.
Reguły zapory sieciowej zabraniają połączenia.
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

Wywołanie systemowe accept4() jest dostępne począwszy od Linuksa 2.6.28; obsługa w glibc pojawiła się od wersji glibc 2.10.

STANDARDY

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

accept4() jest niestandardowym rozszerzeniem systemu Linux.

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).

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 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.

4 grudnia 2022 r. Linux man-pages 6.03