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