NAZWA¶
accept - przyjmowanie połączenia na gnieździe
SKŁADNIA¶
#include <sys/types.h>
#include <sys/socket.h>
int accept(int s, struct sockaddr *addr,
socklen_t *addrlen);
OPIS¶
Uwaga! To tłumaczenie może być nieaktualne!
Funkcja
accept jest używana z połączeniowymi typami
gniazd (
SOCK_STREAM,
SOCK_SEQPACKET i
SOCK_RDM).
Wyciąga ona pierwsze żądanie połączenia z
kolejki oczekujących połączeń, tworzy nowo
podłączone gniazdo o tych samych
właściwościach co
s i alokuje nowy deskryptor
pliku dla gniazda, który to deskryptor jest zwracany. Nowo utworzone
gniazdo nie jest już w stanie nasłuchiwania. Oryginalne gniazdo
s pozostaje po wywołaniiu funkcji niezmienione. Należy
zauważyć, że żadne znaczniki dotyczące
deskryptora pliku (wszystko, co można ustawić za pomocą
F_SETFL, jak stan nieblokujący czy asynchroniczny) nie są
poprzez
accept dziedziczone.
Argument
s 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 łączącej się jednostki,
przekazany przez warstwę komunikacyjną. Dokładny format
adresu przekazywanego w parametrze
addr jest określony poprzez
rodzinę gniazda (zobacz
socket(2) i strony podręcznika
dotyczące odpowiedniego protokołu). Argument
addrlen jest
parametrem wartościowo-wynikowym: powinien początkowo
zawierać rozmiar struktury, na którą wskazuje
addr; po zakończeniu będzie zawierał
rzeczywistą długość zwracanego adresu (w bajtach).
Gdy
addr jest równe NULL, to nic nie jest wypełniane.
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 zwraca EAGAIN.
Aby być informowanym o nadchodzących do gniazda
połączeniach, można użyć
select(2)
lub
poll(2). 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).
Dla niektórych protokołów wymagających
bezpośredniego potwierdzania, takich jak DECNet,
accept
może być uważane za funkcję
zdejmującą 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.
UWAGI¶
Nie zawsze po dostarczeniu
SIGIO musi istnieć oczekujące
połączenie. To samo dotyczy
select(2) i
poll(2),
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,
s
powinno mieć ustawiony znacznik
O_NONBLOCK (zobacz
socket(7)).
WARTOŚĆ ZWRACANA¶
Wywołanie w przypadku błędu zwraca -1. Gdy zakończy
sie pomyślnie zwraca nieujemną liczbę
całkowitą, która jest deskryptorem przyjętego
gniazda.
OBSŁUGA BŁĘDÓW¶
Linuksowe
accept 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¶
Funkcja
accept musi zakończyć się
niepomyślnie gdy:
- EAGAIN lub EWOULDBLOCK
- Gniazdo jest zaznaczone jako nieblokujące a brak jest
połączeń, które mogłyby zostać
przyjęte.
- EBADF
- Deskryptor jest nieprawidłowy.
- ENOTSOCK
- Deskryptor odnosi się do pliku, zamiast do gniazda.
- EOPNOTSUPP
- Przekazane gniazdo nie jest typu SOCK_STREAM.
- EINTR
- Funkcja systemowa została przerwana wskutek odebrania
sygnału przed prawidłowym nawiązaniem
połączenia.
- ECONNABORTED
- Połączenie zostało przerwane.
- EINVAL
- Gniazdo nie nasłuchuje połączeń.
- EMFILE
- Osiągnięte zostało ograniczenie liczby otwartych
deskryptorów plików dla procesu.
- ENFILE
- Osiągnięte zostało systemowe ograniczenie liczby
otwartych deskryptorów plików.
Funkcja
accept może zakończyć się
niepomyślnie gdy:
- EFAULT
- Parametr addr nie znajduje się w przestrzeni adresowej
dostępnej do zapisu dla użytkownika.
- 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.
- EPROTO
- Wystąpił błąd protokołu.
W Linuksie
accept może również
zakończyć się niepomyślnie gdy:
- EPERM
- Reguły firewalla zabraniają połączenia.
- Dodatkowo, dla nowego gniazda mogą być zwracane
błędy sieciowe zdefiniowane
- dla danego protokołu. Różne jądra Linuksa
mogą zwracać inne błędy, takie jak
ENOSR, ESOCKTNOSUPPORT, EPROTONOSUPPORT,
ETIMEDOUT. Wartość ERESTARTSYS może
być obserwowana podczas śledzenia.
ZGODNE Z¶
SVr4, 4.4BSD (funkcja
accept pojawiła się pierwotnie w BSD
4.2). Strona podręcznika BSD opisuje pięć
możliwych zwracanych błędów (EBADF, ENOTSOCK,
EOPNOTSUPP, EWOULDBLOCK, EFAULT). SUSv3 opisuje błędy EAGAIN,
EBADF, ECONNABORTED, EINTR, EINVAL, EMFILE, ENFILE, ENOBUFS, ENOMEM, ENOTSOCK,
EOPNOTSUPP, EPROTO, EWOULDBLOCK. SUSv2 opisuje dodatkowo błędy
EFAULT i ENOSR.
Linuksowe accept _nie_ dziedziczy znaczników gniazda, takich jak
O_NONBLOCK. Takie zachowanie różni się od innych
implementacji gniazd BSD. Przenośne programy nie powinny
zakładać takiego zachowania i zawsze ustawiać dla gniazda
zwracanego przez accept wszystkie potrzebne znaczniki.
UWAGA¶
Trzeci argument
accept był pierwotnie zadeklarowany jako `int *'
(i jest pod libc4 i libc5 oraz na wielu innych systemach, takich jak BSD 4.*,
SunOS 4, SGI); W szkicu standardu POSIX 1003.1g chciano to zmienić na
`size_t *' i tak jest w SunOS 5. Późniejsze szkice POSIX
używają tu `socklen_t *' i tak samo robią Single Unix
Specification i glibc2. Cytując Linusa Torvaldsa:
_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).
ZOBACZ TAKŻE¶
bind(2),
connect(2),
listen(2),
select(2),
socket(2)
Powyższe tłumaczenie pochodzi z nieistniejącego już
Projektu Tłumaczenia Manuali i
może nie być
aktualne. W razie zauważenia różnic między
powyższym opisem a rzeczywistym zachowaniem opisywanego programu lub
funkcji, prosimy o zapoznanie się z oryginalną
(angielską) wersją strony podręcznika za pomocą
polecenia:
- man --locale=C 2 accept
Prosimy o pomoc w aktualizacji stron man - więcej informacji można
znaleźć pod adresem
http://sourceforge.net/projects/manpages-pl/.