Różnice między wybraną wersją a wersją aktualną.
| — |
bio-psiec:udp [2025/11/20 01:29] (aktualna) jkonczak utworzono |
||
|---|---|---|---|
| Linia 1: | Linia 1: | ||
| + | ===== UDP vs TCP ===== | ||
| + | |||
| + | Protokół UDP jest obok protokołu TCP drugim powszechnie używanym protokołem | ||
| + | warstwy transportu. | ||
| + | |||
| + | Inaczej niż TCP, **protokół UDP nie nawiązuje połączeń**. | ||
| + | |||
| + | W TCP między dwoma końcami połączenia jest przesyłany strumień bajtów. | ||
| + | **UDP** zamiast tego **przesyła** wiadomości – **datagramy**, na które składa się | ||
| + | informacja o nadawcy i odbiorcy oraz treść. | ||
| + | \\ | ||
| + | To pozwala na komunikację z wieloma osobami używając jednego gniazda, | ||
| + | a granice logicznych komunikatów są określone. | ||
| + | |||
| + | Protokół TCP numeruje przesyłane bajty i potwierdza odbiór danych, co pozwala | ||
| + | zachować ich kolejność, zadbać o ich kompletność i wysyłać dane z optymalną | ||
| + | prędkością. Protokół UDP nie daje żadnej z tych gwarancji. | ||
| + | |||
| + | ~~Zadanie.#~~ Większość ruchu w Internecie korzysta z TCP. Zastanów się, dlaczego: | ||
| + | <html><div style=margin-top:-1.4em></div></html> | ||
| + | * UDP jest używane przy zapytaniach DNS | ||
| + | * UDP jest preferowane w [[https://pl.wikipedia.org/wiki/WebRTC|WebRTC]] i [[https://pl.wikipedia.org/wiki/Voice_over_Internet_Protocol|VoIP]] | ||
| + | * wiele gier używa UDP | ||
| + | |||
| + | ===== Funkcje sieciowe a UDP ===== | ||
| + | |||
| + | <html><style> | ||
| + | div.wrap_shortcodeexample{display:inline-block;margin-top:-1.4em} | ||
| + | div.wrap_shortcodeexample pre{padding-top:.3em;padding-bottom:.3em} | ||
| + | </style></html> | ||
| + | |||
| + | Tworząc gniazdo UDP należy użyć następujących argumentów: <small>(przykład dla IPv4)</small> | ||
| + | <WRAP shortcodeexample> | ||
| + | <code cpp> | ||
| + | ..... = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); | ||
| + | // lub: socket(PF_INET, SOCK_DGRAM, 0) | ||
| + | </code> | ||
| + | </WRAP> | ||
| + | |||
| + | |||
| + | Jeżeli gniazdo ma pełnić rolę serwera, to trzeba wykonać na nim funkcję ''bind'' | ||
| + | do wybrania lokalnego numer portu. | ||
| + | |||
| + | UDP nie nawiązuje połączeń, więc na gnieździe od razu można wykonywać operacje | ||
| + | odbioru i wysyłania danych. | ||
| + | \\ | ||
| + | Przez to, że UDP nie nawiązuje połączenia, do odbioru i wysyłania wiadomości | ||
| + | należy używać funkcji ''sendto'' i ''recvfrom'' – te funkcje w argumentach | ||
| + | przekazują adresu odbiorcy/nadawcy. | ||
| + | \\ | ||
| + | Do odbioru danych można użyć też funkcji ''read'' i ''recv'', ale wtedy | ||
| + | programista nie dowie się skąd przyszła wiadomość. | ||
| + | |||
| + | Przykład użycia funkcji ''sendto'' i ''recvfrom'': | ||
| + | <WRAP shortcodeexample> | ||
| + | <code cpp> | ||
| + | sockaddr_in dstAddr {...}; | ||
| + | recvCnt = sendto(sock, "msg", 3, 0, (sockaddr*) &dstAddr, sizeof(dstAddr)); | ||
| + | // \arg. jak w send/ \wskazanie dokąd wysłać wiadomość / | ||
| + | </code> | ||
| + | <html><div style=margin-top:-1.4em></div></html> | ||
| + | <code cpp> | ||
| + | sockaddr_in srcAddr; | ||
| + | socklen_t srcAddrLen = sizeof(srcAddr); | ||
| + | sendCnt = recvfrom(sock, buf, 16, 0, (sockaddr*) &srcAddr, &srcAddrLen ); | ||
| + | // \arg. jak w recv/ \ gdzie wpisać adres nadawcy / | ||
| + | </code> | ||
| + | </WRAP> | ||
| + | |||
| + | O tym, czy gniazdo UDP pełni rolę klienta czy serwera decyduje właściwie to, | ||
| + | czy dane są najpierw wysyłane, czy odbierane z ustalonego portu. | ||
| + | |||
| + | <small>W formie ułatwienia BSD socket API pozwala działać gniazdom UDP w trybie | ||
| + | pseudo-połączeniowym - tzn. można wywołać funkcję ''connect'' (która ustali | ||
| + | adres odbiorcy) i dalej korzystać z ''send'' / ''write''. Więcej możesz doczytać | ||
| + | [[https://blog.cloudflare.com/everything-you-ever-wanted-to-know-about-udp-sockets-but-were-afraid-to-ask-part-1/#connected-vs-unconnected|tutaj]]. | ||
| + | </small> | ||
| + | |||
| + | UDP jest zorientowane na wiadomość – wysyła i odbiera całe datagramy. | ||
| + | Jeśli funkcja odbierająca dane zadeklaruje mniejszy bufor niż rozmiar | ||
| + | wiadomości, nadmiarowe dane zostaną odrzucone. | ||
| + | |||
| + | W związku z brakiem połączeń, nie da się na gnieździe UDP wykonać funkcji | ||
| + | ''shutdown'' zamykającej połączenie. | ||
| + | |||
| + | ===== Zadania ===== | ||
| + | |||
| + | ~~Zadanie.#~~ Napisz program, który korzystając z protokołu UDP wyśle dane | ||
| + | (stały ciąg znaków) pod wskazany adres, następnie odbierze dane i się | ||
| + | zakończy. | ||
| + | |||
| + | ~~Zadanie.#~~ Napisz program, który korzystając z protokołu UDP odbierze dane | ||
| + | i odeśle je pod adres nadawcy zmieniając wielkość liter. \\ | ||
| + | <small> | ||
| + | Małe litery można zmienić na wielkie używając: | ||
| + | ''for(int i = 0; i < count; ++i) buf[i] = toupper(buf[i]);'' | ||
| + | Funkcja ''toupper'' jest w bibliotece ''ctype.h''. | ||
| + | </small> | ||
| + | |||
| + | ~~Zadanie.#~~ Napisz program, który będzie w pętli odbierać dane i odsyłać je | ||
| + | pod adresy wszystkich wcześniejszych nadawców. | ||