udp(7)

NAZWA
udp - Protokół datagramów użytkownika dla IPv4

SKŁADNIA
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>

udp_socket = socket(AF_INET, SOCK_DGRAM, 0);

OPIS
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ść.

  Format adresu
UDP stosuje format adresu IPv4 sockaddr_in opisany w ip(7).

  Obsługa błędów
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.

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

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

UDP_SEGMENT (since Linux 4.18)
    Enables UDP segmentation offload. Segmentation offload reduces send(2) cost by transferring multiple datagrams worth of data as a single large packet through the kernel transmit path, even when that exceeds MTU. As late as possible, the large packet is split by segment size into a series of datagrams. This segmentation offload step is deferred to hardware if supported, else performed in software. This option takes a value in the range [0, USHRT_MAX] that sets the segment size: the size of datagram payload, excluding the UDP header. The segment size must be chosen such that at most 64 datagrams are sent in a single call and that the datagrams after segmentation meet the same MTU rules that apply to datagrams sent without this option. Segmentation offload depends on checksum offload, as datagram checksums are computed after segmentation. The option may also be set for individual sendmsg(2) calls by passing it as a cmsg(3). A value of zero disables the feature. This option should not be used in code intended to be portable.

UDP_GRO (since Linux 5.0)
    Enables UDP receive offload. If enabled, the socket may receive multiple datagrams worth of data as a single large buffer, together with a cmsg(3) that holds the segment size. This option is the inverse of segmentation offload. It reduces receive cost by handling multiple datagrams worth of data as a single large packet in the kernel receive path, even when that exceeds MTU. This option should not be used in code intended to be portable.

  Kontrolki systemowe (ioctl)
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).

BŁĘDY
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.

WERSJE
IP_RECVERR pojawiło się w Linuksie 2.2.

ZOBACZ TAKŻE
ip(7), raw(7), socket(7), udplite(7)

Plik źródeł jądra 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.

TŁUMACZENIE
Autorami polskiego tłumaczenia niniejszej strony podręcznika są: Andrzej Krzysztofowicz <ankry@green.mf.pg.gda.pl>, Robert Luberda <robert@debian.org> 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 (https://www.gnu.org/licenses/gpl-3.0.html) 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.