udp - Protokół datagramów użytkownika dla IPv4
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
Jest to implementacja opisanego w RFC 768 protokołu
datagramów użytkownika. Implementuje usługę
bezpołączeniowych, niepewnych pakietów datagramowych.
Kolejność pakietów może się zmienić
przed ich dotarciem do celu, mogą one też zostać
powielone. UDP generuje i sprawdza sumy kontrolne, aby wykryć
błędy transmisji.
Podczas tworzenia gniazda UDP jego adresy: lokalny i zdalny są
nieokreślone. Datagramy można wysyłać natychmiast
za pomocą
sendto(2) lub
sendmsg(2), podając jako
argument prawidłowy adres docelowy. Gdy dla gniazda jest
wywołane
connect(2), ustawiany jest domyślny adres
docelowy i od tego momentu można wysyłać datagramy za
pomocą
send(2) lub
write(2), nie podając adresu
docelowego. Nadal możliwe jest wysyłanie do innych
adresów docelowych, przekazując adres do funkcji
sendto(2) lub
sendmsg(2). Aby odbierać pakiety, gniazdo
może zostać najpierw przypisane do adresu lokalnego za
pomocą
bind(2). W przeciwnym przypadku, warstwa gniazd
automatycznie przypisze wolny port lokalny spoza zakresu zdefiniowanego przez
/proc/sys/net/ipv4/ip_local_port_range i przypisze gniazdo do
INADDR_ANY.
Wszystkie operacje odbioru zwracają tylko jeden pakiet. Gdy pakiet jest
mniejszy niż przekazany bufor, zwracane są tylko dane o
rozmiarze pakietu; gdy pakiet jest większy niż bufor, pakiet
jest obcinany i ustawiany jest znacznik
MSG_TRUNC.
MSG_WAITALL
nie jest wspierane.
Opcje IP mogą być wysyłane lub odbierane za pomocą
opcji gniazda opisanych w
ip(7). Są one przetwarzane przez
jądro tylko wtedy, gdy włączony jest odpowiedni parametr
w
/proc (ale nadal są przekazywane do programu
użytkownika, nawet gdy kontrolka jest wyłączona). Zobacz
ip(7).
Gdy przy wysyłaniu ustawiony jest znacznik
MSG_DONTROUTE, adres
docelowy musi odnosić się do lokalnego adresu interfejsu i
pakiet jest wysyłany jedynie do tego interfejsu.
Domyślnie UDP pod Linuksem wykrywa MTU (Maximum Transmission Unit)
ścieżki. Oznacza to, że jądro utrzymuje informacje
o MTU określonego docelowego adresu IP i zwraca
EMSGSIZE,
jeśli pakiet UDP jest większy niż MTU. W takim wypadku
aplikacja powinna zmniejszyć rozmiar pakietu. Wykrywanie MTU
ścieżki można wyłączyć
ustawiając opcję
IP_MTU_DISCOVER gniazda lub
używając pliku
/proc/sys/net/ipv4/ip_no_pmtu_disc,
szczegóły opisano w
ip(7). Jeśli jest
wyłączone, UDP podzieli wychodzące pakiety UDP,
których rozmiar przekracza MTU, na mniejsze pakiety. Jednakże
wyłączenie wykrywania MTU ścieżki nie jest
zalecane, gdyż ma negatywny wpływ na wydajność i
niezawodność.
UDP stosuje format adresu IPv4
sockaddr_in opisany w
ip(7).
Wszystkie błędy krytyczne są przekazywane do programu
użytkownika jako wartość zwracana, nawet gdy gniazdo nie
jest połączone. Dotyczy to także
błędów asynchronicznych otrzymywanych z sieci.
Można też otrzymać błąd dotyczący
pakietu wcześniej wysłanego z danego gniazda. To zachowanie
różni się od wielu innych implementacji gniazd BSD,
które nie przekazują żadnych błędów,
gdy gniazdo nie jest połączone. Zachowanie Linuksa ma oparcie w
RFC 1122.
Dla zgodności z kodem odziedziczonym w wersjach 2.0 i 2.2 jądra
Linuksa było możliwe ustawienie opcji
SOL_SOCKET
SO_BSDCOMPAT, aby otrzymywać błędy zdalne tylko
wtedy, gdy gniazdo jest połączone (z wyjątkiem
EPROTO i
EMSGSIZE). Błędy wygenerowane lokalnie
są zawsze przekazywane. Obsługa tej opcji została
usunięta w kolejnych wersjach jądra; szczegóły
można znaleźć w
socket(7).
Gdy włączona jest opcja
IP_RECVERR, wszystkie
błędy są przechowywane w kolejce
błędów gniazda i mogą być odczytywane za
pomocą
recvmsg(2) z ustawionym znacznikiem
MSG_ERRQUEUE.
Systemowe ustawienia parametrów można zmieniać,
używając plików z katalogu
/proc/sys/net/ipv4/.
-
udp_mem (od Linuksa 2.6.25)
- Jest wektorem trzech liczb całkowitych
zawierających numery stron, które mogą być
kolejkowane przez wszystkie gniazda UDP.
- min
- Do chwili przekroczenia podanej liczny stron, UDP nie
przejmuje się zużyciem pamięci. Kiedy
ilość pamięci zaalokowanej przez UDP przekroczy
tę liczbę, UDP zaczyna zmniejszać zużycie
pamięci.
- pressure
- Wartość została wprowadzona,
naśladując tcp_mem (patrz tcp(7))
- max
- Liczba stron, które mogą być
kolejkowane przez wszystkie gniazda UDP.
- Domyślne wartości powyższych trzech
pozycji są wyliczane podczas startu systemu na podstawie
ilości dostępnej pamięci.
-
udp_rmem_min (liczba całkowita;
wartość domyślna: PAGE_SIZE; od Linuksa 2.6.25)
- Minimalny rozmiar, bajtach, bufora otrzymywania
używanego z umiarem przez gniazda UDP. Każde gniazdo UDP
jest w stanie użyć tego rozmiaru do otrzymywania danych,
nawet jeśli całkowita liczba stron gniazd UDP przekroczy
udp_mem.
-
udp_wmem_min (liczba całkowita;
wartość domyślna: PAGE_SIZE; od Linuksa 2.6.25)
- Minimalny rozmiar, bajtach, bufora wysyłania
używanego z umiarem przez gniazda UDP. Każde gniazdo UDP
jest w stanie użyć tego rozmiaru do wysyłania danych,
nawet jeśli całkowita liczba stron gniazd UDP przekroczy
udp_mem.
Aby ustawić lub pobrać opcję gniazda UDP, należy
wywołać
getsockopt(2) w celu odczytania lub
setsockopt(2) w celu zapisania opcji, ustawiając argument
poziomu opcji na
IPPROTO_UDP. Jeśli nie zaznaczono inaczej,
optval jest wskaźnikiem do
int.
Following is a list of UDP-specific socket options. For details of some other
socket options that are also applicable for UDP sockets, see
socket(7).
-
UDP_CORK (od Linuksa 2.5.44)
- Jeśli ta opcja zostanie włączona, to
wszystkie dane na wyjściu tego gniazda są
łączone do pojedynczego datagramu, który zostanie
wysłany, kiedy ta opcja zostanie wyłączona. Opcja ta
nie powinna być używana w kodzie, który w zamierzeniu
ma być przenośny.
Do poniższych kontrolek wejścia/wyjścia można
uzyskać dostęp za pomocą funkcji
ioctl(2).
Prawidłowa składnia to:
int value;
error = ioctl(udp_socket, ioctl_type, &value);
-
FIONREAD (SIOCINQ)
- Pobiera jako argument wskaźnik do liczby
całkowitej. Zwraca w tej zmiennej rozmiar następnego
oczekującego datagramu lub 0, w razie braku oczekujących
datagramów. Ostrzeżenie: FIONREAD nie daje
możliwości rozróżnienia przypadku braku
datagramów od przypadku, w którym następny
oczekujący datagram zawiera zero bajtów danych. Żeby
rozróżnić takie sytuacje bezpieczniej jest
używać select(2), poll(2) lub
epoll(7).
-
TIOCOUTQ (SIOCOUTQ)
- Returns the number of data bytes in the local send queue.
Supported only with Linux 2.4 and above.
Ponadto wspierane są wszystkie kontrolki wejścia/wyjścia
opisane w
ip(7) i
socket(7).
Przy wysyłaniu lub odbieraniu za pośrednictwem gniazd UDP
mogą wystąpić wszystkie błędy zdefiniowane
dla
socket(7) lub
ip(7).
- ECONNREFUSED
- Z adresem docelowym nie był skojarzony żaden
odbiorca. Może to być spowodowane przez uprzednie
wysłanie pakietu za pośrednictwem danego gniazda.
IP_RECVERR pojawiło się w Linuksie 2.2.
ip(7),
raw(7),
socket(7),
udplite(7)
The kernel source file
Documentation/networking/ip-sysctl.txt.
RFC 768 dla protokołu datagramów użytkownika.
RFC 1122 dla wymagań hostów.
RFC 1191 dla opisu badania MTU ścieżki.
Autorami polskiego tłumaczenia niniejszej strony podręcznika
są: Andrzej Krzysztofowicz <
[email protected]>, Robert
Luberda <
[email protected]> i Michał Kułach
<
[email protected]>
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
[email protected]