accept(2) System Calls Manual accept(2) NAZWA accept, accept4 - przyjmuje polaczenia na gniezdzie BIBLIOTEKA Standardowa biblioteka C (libc, -lc) SKLADNIA #include int accept(int sockfd, struct sockaddr *_Nullable restrict addr, socklen_t *_Nullable restrict addrlen); #define _GNU_SOURCE /* zobacz feature_test_macros(7) */ #include int accept4(int sockfd, struct sockaddr *_Nullable restrict addr, socklen_t *_Nullable restrict addrlen, int flags); OPIS Wywolanie systemowe accept() jest uzywane z polaczeniowymi typami gniazd (SOCK_STREAM, SOCK_SEQPACKET). Wyciaga ona pierwsze zadanie polaczenia z kolejki oczekujacych polaczen dla nasluchujacego gniazda sockfd, tworzy nowo podlaczone gniazdo i zwraca nowy deskryptor pliku odnoszacy sie do tego gniazda. Nowo utworzone gniazdo nie jest juz w stanie nasluchiwania. Oryginalne gniazdo sockfd pozostaje po tym wywolaniu niezmienione. Argument sockfd jest gniazdem, ktore zostalo utworzone wywolaniem socket(2), przywiazanym do adresu lokalnego z pomoca bind(2), i nasluchujacym polaczen po wywolaniu listen(2). Argument addr jest wskaznikiem do struktury sockaddr. Do struktury tej jest wpisywany adres drugiego gniazda, przekazany przez warstwe komunikacyjna. Dokladny format zwracanego adresu addr jest okreslony poprzez rodzine adresowa gniazda (zobacz socket(2) i strony podrecznika dotyczace odpowiedniego protokolu). Gdy addr jest rowne NULL, to nic nie jest wypelniane; w takim przypadku addrlen nie jest uzywane i rowniez powinno wynosic NULL. Argument addrlen jest parametrem wartosciowo-wynikowym: powinien poczatkowo zawierac rozmiar (w bajtach) struktury, na ktora wskazuje addr; po zakonczeniu bedzie zawieral rzeczywista dlugosc zwracanego adresu. Zwracany adres jest przycinany, jesli udostepniony bufor jest zbyt maly; w tym przypadku addrlen zwroci wartosc wieksza niz byla podana w wywolaniu. Jesli nie ma zalegajacych polaczen w kolejce, a gniazdo nie jest zaznaczone jako nieblokujace, to accept() blokuje proces wywolujacy az do uzyskania polaczenia. Gdy gniazdo jest zaznaczone jako nieblokujace i nie ma zalegajacych polaczen w kolejce, accept() zawodzi z bledem EAGAIN lub EWOULDBLOCK. Aby byc informowanym o nadchodzacych do gniazda polaczeniach, mozna uzyc select(2), poll(2) lub epoll(7). Podczas proby nowego polaczenia zostanie dostarczone zdarzenie odczytywalnosci (readable) i wtedy mozna wywolac accept() aby uzyskac gniazdo tego polaczenia. Inaczej, mozna ustawic gniazdo tak, by dostarczalo SIGIO za kazdym razem, gdy sie na nim cos zacznie dziac; szczegoly mozna znalezc w socket(7). Jesli flags wynosi 0, to accept4() jest taka sama jak accept(). Nastepujace wartosci flags mozna zsumowac logicznie, aby uzyskac odmienne zachowanie: SOCK_NONBLOCK Ustawia znacznik statusu pliku O_NONBLOCK na otwartym deskryptorze pliku (zob. open(2) do ktorego odnosi sie nowy deskryptor pliku. Uzycie tego znacznika zapobiega dodatkowym wywolaniom do fcntl(2) przy uzyskaniu tego samego efektu. SOCK_CLOEXEC Ustawia znacznik zamkniecia-przy-wykonaniu (FD_CLOEXEC) na nowym deskryptorze pliku. Opis znacznika O_CLOEXEC w podreczniku open(2) informuje o przypadkach, w ktorych moze sie to okazac przydatne. WARTOSC ZWRACANA W przypadku sukcesu, te wywolania systemowe zwracaja deskryptor pliku dla zaakceptowanego gniazda (nieujemna liczbe calkowita). W razie zaistnienia bledu, zwracane jest -1, ustawiane jest errno wskazujac blad, a addrlen nie ulega zmianie. Obsluga bledow Linuksowe accept (i accept4()) przekazuje zalegajace juz na nowym gniezdzie bledy sieciowe jako kod bledu z accept(). Zachowanie to rozni sie od implementacji gniazd w BSD. Dla sensownego dzialania, aplikacja powinna wykrywac po wykonaniu accept() bledy sieciowe, zdefiniowane dla danego protokolu i traktowac je jak EAGAIN, czyli ponawiac probe. W wypadku TCP/IP sa to ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH, EOPNOTSUPP i ENETUNREACH. BLEDY EAGAIN lub EWOULDBLOCK Gniazdo jest oznaczone jako nieblokujace i nie wystepuja polaczenia do zaakceptowania. POSIX.1-2001 i POSIX.1-2008 zezwalaja na zwrocenie w takim przypadku dowolnego z dwoch bledow i nie wymagaja, aby mialy one taka sama wartosc, dlatego przenosne aplikacje powinny sprawdzic oba przypadki. EBADF sockfd nie jest deskryptorem otwartego pliku. ECONNABORTED Polaczenie zostalo przerwane. EFAULT Argument addr nie znajduje sie w przestrzeni adresowej dostepnej do zapisu dla uzytkownika. EINTR Wywolanie systemowe zostalo przerwane wskutek odebrania sygnalu przed prawidlowym nawiazaniem polaczenia; zob. signal(7). EINVAL Gniazdo nie nasluchuje polaczen lub addrlen jest nieprawidlowe (np. jest ujemne). EINVAL (accept4()) nieprawidlowa wartosc w flags. EMFILE Zostalo osiagniete ograniczenie na liczbe otwartych deskryptorow plikow dla procesu. ENFILE Zostalo osiagniete systemowe ograniczenie na calkowita liczbe otwartych plikow. ENOBUFS ENOMEM Jest niedostateczna ilosc wolnej pamieci. Oznacza to zazwyczaj, ze istnieje ograniczenie dla przydzielania pamieci na bufory gniazd, nie zas ze zabraklo pamieci w systemie. ENOTSOCK Deskryptor pliku sockfd nie odnosi sie do gniazda. EOPNOTSUPP Przekazane gniazdo nie jest typu SOCK_STREAM. EPERM Reguly zapory sieciowej zabraniaja polaczenia. EPROTO Wystapil blad protokolu. Dodatkowo, dla nowego gniazda moga byc zwracane bledy sieciowe zdefiniowane dla danego protokolu. Rozne jadra Linux moga zwracac inne bledy, takie jak ENOSR, ESOCKTNOSUPPORT, EPROTONOSUPPORT, ETIMEDOUT. Wartosc ERESTARTSYS moze byc obserwowana podczas sledzenia. WERSJE W Linuksie, nowe gniazdo zwracane przez accept() nie dziedziczy znacznikow statusu pliku, takich jak O_NONBLOCK i O_ASYNC od nasluchujacego gniazda. Takie zachowanie rozni sie od tradycyjnej implementacji gniazd BSD. Przenosne programy nie powinny polegac na dziedziczeniu lub niedziedziczeniu znacznikow statusu pliku i zawsze ustawiac wprost wszystkie wymagane znaczniki na gniezdzie zwracanym przez accept(2). STANDARDY accept() POSIX.1-2008. accept4() Linux. HISTORIA accept() POSIX.1-2001, SVr4, 4.4BSD (accept() pojawilo sie pierwotnie w 4.2BSD). accept4() Linux 2.6.28, glibc 2.10. UWAGI Nie zawsze po dostarczeniu SIGIO musi istniec oczekujace polaczenie. To samo dotyczy select(2), poll(2) i epoll(7), zwracajacych zdarzenie odczytywalnosci, poniewaz polaczenie moglo zostac usuniete przez asynchroniczny blad sieci lub inny watek, przed wywolaniem accept(). Jesli to sie zdarzy, to wywolanie bedzie blokowac, oczekujac nastepnego polaczenia. Aby upewnic sie, ze accept() nigdy nie bedzie blokowalo, przekazane gniazdo sockfd powinno miec ustawiony znacznik O_NONBLOCK (zobacz socket(7)). Dla niektorych protokolow wymagajacych bezposredniego potwierdzania, takich jak DECnet, accept() moze byc uwazane za wywolanie zdejmujace z kolejki nastepne zadanie polaczenia, nie powodujac potwierdzenia. Potwierdzenie mozna spowodowac przez normalny odczyt, lub zapis na nowym deskryptorze pliku, a odrzucenie mozna spowodowac, zamykajac gniazdo. Obecnie pod Linuksem taka semantyke ma tylko DECnet. Typ socklen_t W oryginalnej implementacji gniazd BSD (i innych starszych systemow) trzeci argument accept() byl deklarowany jako int *. Szkic POSIX.1g planowal zmienic to na size_t *C; pozniejsze standardy POSIX oraz glibc 2.x posiadaja socklen_t * . PRZYKLADY Zobacz bind(2). ZOBACZ TAKZE bind(2), connect(2), listen(2), select(2), socket(2), socket(7) TLUMACZENIE Autorami polskiego tlumaczenia niniejszej strony podrecznika sa: Przemek Borys , Andrzej Krzysztofowicz i Michal Kulach Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI. Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy dyskusyjnej . Linux man-pages 6.06 31 pazdziernika 2023 r. accept(2)