Komunikacja bezpołączeniowa
UDP (z ang. User Datagram Protocol – protokół datagramów użytkownika) to bardzo lekki protokół umożliwiający przesyłanie komunikatów między klientem i serwerem, o następujących cecach:
- brak utrzymania informacji o stanie połączenia,
 - brak potwierdzenia dotarcia komunikatu (w efekcie brak retransmisji w przypadku utraty komunikatu)
 - mały narzut komunikacyjny (wielkość nagłówka to 64 bity, podczas gdy w TCP to 160 bitów),
 - brak kontroli nad kolejnością docierania komunikatów (w szczególnych przypadkach jeden datagram może nawet zostać dostarczony dwa razy),
 - minimalne informacje przekazywane, 4 pola po 16 bitów:
- port źródłowy
 - port docelowy (oba porty określają strony komunikacji),
 - suma kontrolna
 - długość datagramu UDP.
 
 
Podobnie jak w przypadku TCP porty o wartości poniżej 1024 są zarezerwowane dla znanych usług i wymagają uprawnień administratora w celu komunikacji.
Wykorzystywane funkcje:
- sockfd = socket(int socket_family, int socket_type, int protocol); (dla komunikacji UDP należy podać odpowiednio AF_INET, SOCK_DGRAM, 0)
 - ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
 - ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
 - ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
 - ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
 - struktura msghdr: 
123456789struct msghdr {void *msg_name; /* optional address */socklen_t msg_namelen; /* size of address */struct iovec *msg_iov; /* scatter/gather array */size_t msg_iovlen; /* # elements in msg_iov */void *msg_control; /* ancillary data, see below */size_t msg_controllen; /* ancillary data buffer len */int msg_flags; /* flags on received message */}; - struktura iovec: 
1234struct iovec { /* Scatter/gather array items */void *iov_base; /* Starting address */size_t iov_len; /* Number of bytes to transfer */}; 
Funkcje sendto i recvfrom są prostsze i będziemy je wykorzystywać na zajęciach.
UDP server:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53  | 
						#include <stdio.h> #include <string.h> #include <netinet/in.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netdb.h>  char buf[512]; int main(int argc, char **argv) {     struct sockaddr_in myaddr, endpoint;     int sdsocket, r;     socklen_t addrlen;     unsigned int port;     printf("Na ktorym porcie mam sluchac? : ");     scanf("%u", &port);     if ((sdsocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {         printf("socket() nie powiodl sie\n");         return 1;     }     myaddr.sin_family = AF_INET;     myaddr.sin_port = htons(port);     myaddr.sin_addr.s_addr = INADDR_ANY;     if (         bind(sdsocket,              (struct sockaddr*) &myaddr,              sizeof(struct sockaddr_in)) < 0) {         printf("bind() nie powiodl sie\n");         return 1;     }     addrlen = sizeof(struct sockaddr_in);     while (1) { /* nieskonczona petla */         memset(buf, 0, 512);         r = recvfrom(sdsocket,                      buf,                      512,                      0,                      (struct sockaddr*) &endpoint,                      &addrlen);         printf("Wiadomosc od %s: %s\n",                inet_ntoa(endpoint.sin_addr),                buf);     }         return 0; }  | 
					
UDP client:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41  | 
						#include <stdio.h> #include <string.h> #include <netinet/in.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netdb.h>  char buf[512]; int main(int argc, char **argv) {     struct sockaddr_in adr;     int gniazdo, r;     unsigned int port;     char abcd[512];         printf("Podaj adres IP odbiorcy: ");     scanf("%s", abcd);     printf("Podaj numer portu odbiorcy: ");     scanf("%u", &port);     gniazdo = socket(AF_INET, SOCK_DGRAM, 0);     adr.sin_family = AF_INET;     adr.sin_port = htons(port);     adr.sin_addr.s_addr = inet_addr(abcd);     printf("Podaj wiadomosc: ");     fflush(stdout); fgetc(stdin);     fgets(buf, 512, stdin);     r = sendto(gniazdo,                buf,                512,                0,                (struct sockaddr*) &adr,                sizeof(adr));     if (r != 512) printf("sendto() nie powiodl sie\n");     else printf("Wiadomosc wyslana.\n");     close(gniazdo);     return 0; }  | 
					
Zadania:
W oparciu o kod z Przykładu 2 zaimplementować następujące przypadki:
- Przesyłanie bloków 10000-bajtowych za pomocą protokołu UDP z pomiarem czasu. Program powinien działać wg schematu pomiar czasu, socket, 100 razy sendto i recvfrom, close, pomiar czasu, podanie czasu podzielonego przez 100.
 - Przesyłanie bloków 10000-bajtowych za pomocą protokołu TCP w jednej sesji z pomiarem czasu. Program powinien działać wg schematu pomiar czasu, socket, connect, 100 razy send i recv, close, pomiar czasu, podanie czasu podzielonego przez 100.
 
Przeimplementować należy zarówno stronę klienta, jak i stronę serwera.
Program proszę uruchamiać na dwóch komputerach w laboratoriach wydziału aby uzyskane wyniki faktycznie uwzględniały przesyłanie danych przez sieć.
Uwagi:
- przykłady klienta i serwera UDP oraz zadanie wzięte ze strony Tomasza Tyrakowskiego http://www.staff.amu.edu.pl/~ttomek/sik/cwiczenia2.html),
 - opisy struktur i dokumentacje protokołu wzięte z manuala (podręcznika systemowego linux).
 
