===== 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:
* 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 ===== Tworząc gniazdo UDP należy użyć następujących argumentów: (przykład dla IPv4) ..... = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); // lub: socket(PF_INET, SOCK_DGRAM, 0) 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'': sockaddr_in dstAddr {...}; recvCnt = sendto(sock, "msg", 3, 0, (sockaddr*) &dstAddr, sizeof(dstAddr)); // \arg. jak w send/ \wskazanie dokąd wysłać wiadomość /
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 /
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. 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]]. 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. \\ 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''. ~~Zadanie.#~~ Napisz program, który będzie w pętli odbierać dane i odsyłać je pod adresy wszystkich wcześniejszych nadawców.