Opis problemu
Komunikacja sieciowa jest bardzo elastycznym elementem komunikacji, jednakże niesie za sobą narzut obliczeniowy w postaci obsługi stosu TCP/IP po stronie klienta i serwera.
W przypadku gdy aplikacja klienta i serwera działają w tym samym systemie operacyjnym (na tym samym komputerze lub maszynie wirtualnej), wówczas narzut ten powoduje niepotrzebne wykorzystanie portów oraz obliczeń wykonywanych po stronie jądra.
Sockety unix – wprowadzenie i definicje
Struktura opisująca gniazdo unix wygląda następująco:
Przypisanie wartości strukturze sockaddr_un:
Funckje wykorzystane w celu utworzenia serwera:
- unsingned int socket(int domain, int type, int protocol); – funkcja tworząca gniazdo. W przypadku gdy chcemy utworzyć gniazdo typu UNIX, należy podać jako domain AF_UNIX, type SOCK_STREAM, a protocol wartość 0.
- int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); – po utworzeniu struktury sockfd jest ona zadeklarowana w pamięci, ale podobnie jak dla protokołu IP nie miała jeszcze żadnego adresu przypisanego, tak dla gniazd UNIX następuje powiązanie z adresem pliku (a konkretniej strukturą opisującą adres gniazda).
- int listen(int sockfd, int backlog); – funkcja oznaczająca gniazdo sockfd jako gniazdo, które będzie wykorzystywane do otrzymywania nadchodzących połączeń. W przypadku gdy system otrzyma więcej niż jedno połączenie naraz, zostanie utworzona kolejka FIFO o maksymalnym rozmiarze backlog. Funkcję można wywołać tylko dla gniazd połączeniowych (SOCK_STREAM).
- int accept(int sockfd, struct sockaddr *newsockfd, socklen_t *address_len); – wywołanie systemowe (czyli funkcja po stronie jądra) uruchamiane na utworzonym wczesniej gnieździe sockfd (będącym w trybie listen), w celu otrzymania połączenia. W przypadku gdy w danym momencie jest więcej niż jedno połączenie, system operacyjny zapewnia kolejkę oczekujących połączeń (FIFO). W takim przypadku jest brane pierwsze z kolejki. Tworzony i zwracany (jako int) jest nowy deskryptor newsockfd. Oryginalne gniazdo nie zmienia stanu. Wywołanie accept wykorzystywane jest tylko do połączeniowych protokołów (SOCK_STREAM).
Funkcje wykorzystywane w celu utworzenia klienta:
- funkcja socket – działa tak samo jak dla aplikacji serwera.
- int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); – wywołanie connect nawiązuje połączenie do adresu opisanego przez strukturę addr i łączy utworzonego połączenie do deskryptora sockfd.
Funkcje czytania i pisania nie zmieniają się w porównaniu do normalnych gniazd protokołu IP.
Przykłady
Przykładowa aplikacja serwera:
Przykładowa aplikacji klienta:
Zadanie:
W oparciu o kod z tych i poprzednich zajęć zaimplementować następujące przypadki:
- Przesyłanie bloków 1000-bajtowych za pomocą protokołu gniazd TCP z pomiarem czasu. Program powinien działać wg schematu pomiar czasu, socket, 1000 razysendto i recvfrom, close, pomiar czasu, podanie czasu podzielonego przez 100.
- Przesyłanie bloków 1000-bajtowych za pomocą protokołu gniazd UNIX z pomiarem czasu. Program powinien działać wg schematu pomiar czasu,socket, connect, 1000 razy send i recv, close, pomiar czasu, podanie czasu podzielonego przez 100.
Wyniki proszę pokazać prowadzącemu.
Uwaga:
Przykłady aplikacji klienta i serwera to modyfikacje programów ze strony http://beej.us/guide/bgipc/output/html/multipage/unixsock.html