---
# System prepended metadata

title: Untitled

---

## Systemy operacyjne - lista 9

### Zadanie 1
![](https://i.imgur.com/n98ze9K.png)

Chapter 1 - cebula ma warstwy, ogry mają warstwy, no to internet też musi mieć warstwy.

Zwróćmy teraz uwagę na protokoły sieciowe. żeby zapewniśc strukturę systemowi protokołów sieciowych, projektanci sieci organizują
protokoły oraz sprzęt i oprogramowanie sieciowe, które je implementują - w warstwy. Każdy protokół należy do jednej z warstw. Nas interesują usługi, jakie dana warstwa oferuje warstwie znajdującej się powyżej - tzw. model usługowy warstwy
model usługowy warstwy. Każda warstwa świadczy swoje usługi poprzez
(1) wykonywanie pewnych czynności w obrębie tej warstwy oraz (2) korzystanie z usług warstwy znajdującej się bezpośrednio pod nią.
Jedni mówią, że fajno, bo warstwy są od siebie oddzielone, można zrobić update jakiejś warstwy i jest gitara bo nie ruszamy innych a inni że do dupy bo niektóre funkcjonalności mogą się powtarzać, protokoły potrzebują informacji z innych warstw więc całą tą ideę separacji chuj strzela no i wgl to na chuj tak kombinować.

*Protokoły warstwy aplikacji* -
W warstwie aplikacji znajdują się aplikacje sieciowe i ich protokoły.Warstwa aplikacji internetu obejmuje wiele protokołów, takich jak np. HTTP (umożliwiający żądanie i przesyłanie dokumentów internetowych), SMTP
(umożliwiający przesyłanie wiadomości e-mail) oraz FTP (umożliwiający
przesyłanie plików między dwoma systemami końcowymi). Niektóre funkcje sieciowe, takie jak np.tłumaczenie przyjaznych dla człowieka nazw internetowych, takich jak
www.ietf.org na 32-bitowy adres sieciowy, są również wykonywane za pomocą specyficznego protokołu warstwy aplikacji, zwanego Domain Name System (DNS). 

*Protokoły warstwy transportowej* -
służy do transportowania wiadomości warstwy aplikacji pomiędzy dwoma punktami końcowymi. W internecie istnieją dwa protokoły transportowe - TCP i UDP.

TCP gwarantuje dostarczenie wiadomości warstwy aplikacji do miejsca przeznaczenia oraz flow control (dopasowanie prędkości nadawcy/odbiorcy).
Tcp rozbija również długie wiadomości na krótsze segmenty (okazuje się, że małe pakieciki z reguły są przesyłane szybciej niż duże i potem są jakoś sprytnie sklejane do kupy) i zapewnia mechanizm kontroli zatłoczenia, dzięki któremu źródło spowalnia swoją szybkość transmisji gdy sieć jest zatłoczona.

UDP natomiast hest usługą do dupy (znaczy nie wiem czy tak jest). Nie zapewnia niezawodności, kontroli przepływu ani kontroli przeciążenia.


*Protokoły warstwy sieciowej* -
warstwa ta jest odpowiedzialna za transportowanie pakietów warstwy sieciowej, zwanych datagramami, z jednego hosta do drugiego. Protokoły warstwy transportowej
przekazują segment warstwy transportowej i adres docelowy do warstwy sieciowej, niemalże jak nadawanie listu na pocztę z czyimś adresem. Warstwa sieciowa, udostępnia wtedy usługę dostarczenia segmentu do warswy transportowej hosta docelowego.
Jednym z protokołów warstwy transportowej jest protokół IP, który definiuje pola w datagramie, a także sposób w jaki systemy końcowe i routery działają na te pola. W tej warstwie są też protokoły routingu, które określają trasy datagramów od źródła do końcowego hosta.

*Protokoły warstwy łączą* - 
Warstwa sieciowa wysyła datagramy które wędrują przez wiele routerów będących pomiędzy źródłem a celem. Aby wysyłać pakiety z jednego węzła (hosta lub routera) do drugiego, warstwa sieciowa polega na serwisach warstwy łącza i jej protokołach. Warstwa sieciowa w każdym napotkanym węźle przekazuje datagram warstwie łącza, która przekazuje go do innego węzła, z którego znów protokoły warstwy łącza przekazują go do warstwy sieciowej.

*Warstwa fizyczna* - podczas gdy praca warstwy łącza polega na przekazywania całych ramek z jednego elementu sieci do sąsiadującego, praca warstwy fizycznej polega na przenoszeniu poszczególnych bitów w obrębie ramki z jednego węzła do następnego.

Application Layer         -> Message
Transport Layer           -> Segment
Network Layer             -> Datagram
Link Layer                -> Frame
To wszystko razem w kupie -> Pakiet

![](https://i.imgur.com/24mCvLm.png)


*Kapsułkowanie* - Takie dokładanie kolejnych warstw danych, znowu wartswy-ogry, no wcześniej było tyle mówione o warstwach no to chyba wiadomix czemu to się w warstwy pakuje

1. Sockety są zasobożerne i działają 1-1, w sensie jeśli chcielibyśmy wysłać informację do x procesów to potrzeba by było do tego x socketów, 

### Zadanie 2
![](https://i.imgur.com/U5GVf9a.png)

UDP (user datagram protocol)

- protokół bezpołączeniowy, serwer i klient nie tworzą połączenia przed rozpoczęciem transmisji danych, tak po prostu wysyłają między sobą pakiety
- niewielki narzut danych sterujących
- używamy pary funkcji sendto() i recvfrom(), w których określamy adres hosta do którego wysyłamy lub od którego odbieramy dane
- brak gwaracji co do kompletności przesłanych danych ani ich kolejności

TCP (transmission control protocol)

- protokół połączeniowy, serwer i klient tworzą pomiedzy sobą połączenie, leci informacja, że chce pogadać i dopieo wtedy może nastąpić prawdziwa komunikacja
- odbiór każdego segmentu jest potwierdzany, jeśli brak potwierdzenia - wyślij jeszcze raz (i tam zdaje się poczekaj już trochę dłużej na potwierdzenie - szacuje sobie jakiś round-trip time żeby wiedzieć ile zaczekać)
- gwarantuje poskładanie ich ładnie do kupy jeśli zostały rozpierdolone na lewo i prawo w złej kolejności i zrobił się syf
- implementuje flow-control odbiorca może skomunikować się z nadawcą i mówi mu tak "wariacie we no kurwa poczekaj bo bufor mi się zapchał" a jak już bufor się zwolni to mówi "dobra kurwa lecisz dalej z tematem" (w UDP możemy stracić pakiety bo nie nadążymy z ich przetwarzaniem - kolejny powód dla którego jebać UDP) a no i chyba poza tym to nadawca mówi normalnie ile jeszcze można w niego ładować ale jako że temacik jest dynamiczny to to że chwle temu nadawca miał/nie miał miejsca do momentu w którym dostał pakiecik o rozmiarze x mogło się zmienić, wtedy dzieje się to co wyżej idk trudne się wylosowało
- jakieś se tam flagi wysyłają odbiorca mówi FIN skończyłem i wymaga, żeby nadawca powiedział ACK przyjęte bez odbioru no ewentualnie można zajebać RST bo się spierdoliło i wtedy wyjebongo czy odbiorca coś odpowie czy nie, można gościa zsagować.

*Komunikacja duplexowa (full-duplex)* - w każdej chwili możliwe jest przesyłanie danych w obie strony,

*pól duplexowa (half-duplex)* - w danej chwili komunikacja może odbywać się tylko w jedną stronę (wysyłamy/odbieramy naprzemiennie)

Segmenciory są numerowane i jak np mamy 2137 bajtów które są wysłane to pierwszy pakiet ma 1024 bajty a drugi ma 2137-1024 i jak najpierw przyjdą te 2137-1024 to odbiorca wie że musi je swapnąć tak jak pan jezus powiedział. Jak sobie radzi ze zgubieniem? No nadawca nie potwierdzi że otrzymał, więc odbiorca wyśle jeszcze raz (robi retransmisje), więc jest gitara ALE jeśli zdarzy się tak, że tak naprawdę nie zostały zgubione, ale się zapchały gdzieś albo coś, i odbiorca dostanie jakiś pakiecik 2 razy to się pokapuje że to duplikat i go odrzuci.

### Zadanie 3
![](https://i.imgur.com/MJzdNxl.png)
![](https://i.imgur.com/m6l9fEd.png)

int socket(int domain, int type, int protocol);
1. Socket() - tworzy punkt końcowy dla komunikacji i zwraca deskryptor pliku, który odnosi się do tego punktu końcowego.
 - domain - oznacza rodzinę protokołów które będą używane do komunikacji.
![](https://i.imgur.com/iRxbRRz.png)
 - type - typ socketu, określa semantykę komunikacji
![](https://i.imgur.com/UwG7Gh6.png)
 - protocol - określa jaki protokół będzie używany
![](https://i.imgur.com/EB6HOmY.png)

2. Connect() - używane przez klienta TCP do nawiązania połączenia z serwerem TCP

3. Bind() - używane do związania socketa z parą ip:port na serwerze

4. Listen() - używane tylko przez klienta TCP, markuje socket jako aktywny, drugi argument określa maksymalny rozmiar klientów czekających na obsłużenie, każdy kolejny jest odrzucany (dostaje connection refused)

5. Accept() - Wywołanie systemowe accept() jest używane z typami gniazd opartymi na połączeniach (SOCK_STREAM, SOCK_SEQPACKET).  Wyciąga ono pierwsze żądanie połączenia z kolejki oczekujących połączeń dla gniazda nasłuchującego, sockfd, tworzy nowe połączone gniazdo i zwraca nowy deskryptor pliku odnoszący się do tego gniazda.  Nowo utworzone gniazdo nie jest w stanie nasłuchiwania.  Oryginalne gniazdo sockfd nie jest dotknięte przez to wywołanie.


*Gniazdo strumieniowe* - gniazda wykorzystywane w komunikacji TCP, oparte na połączeniach, umożliwiają sekwencyjny przepływ danych, no gwarantują to co TCP

*Porty ulotne (ephernal)* - przypisywane automatycznie przez kernela klienta (tworzy parę lokalne_ip:host) kiedy klienty wykona żądanie połączenia, jak nazwa wskazuje są ULOTNE, przypisywane tylko na czas tego konkretnego połączenia i później zwalniane, jądro wybiera losowo (chyba) dostępny port z listy dostępnych portów (masło maślane ale chodzi o to, że na listę wszystkich możliwych portów - te 64k coś tam ileś pierwszych jest na stałe przypisanych)

Co specyfikuje drugi argument wywołania systemowego listen(2)? 

```
int listen(int sockfd, int backlog);

listen() marks the socket referred to by sockfd as a passive socket, that is, as a socket that will be used to accept incoming connection requests using accept(2).

The sockfd argument is a file descriptor that refers to a socket of type SOCK_STREAM or SOCK_SEQPACKET.

The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow.  If a connection request arrives when the queue is full, the client may receive an error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, the request may be ignored so that a later reattempt at connection succeeds.
```
Jest to wskazówka dla jądra ile requestów może zakolejkować, zanim zacznie je odrzucać

Skąd serwer wie, że klient zakończył połączenie - ma swoją własną szklaną kulę i się jej pyta (dostaje EOF od klienta)



### Zadanie 4
![](https://i.imgur.com/zk6aKec.png)
![](https://i.imgur.com/M6DxhSU.png)

Czemu, w przeciwieństwie do TCP, serwer może rozpocząć pracę zaraz po wykonaniu funkcji bind(2)? - Ponieważ w UDP nie musi nawiązywać połączenia z klientem, nie ma połączenia, można od razu pracować

Z jakiej przyczyny interfejs read(2) i write(2) po stronie serwera może być niewystarczający?

Ponieważ w przypadku UDP trzeba odczytać adres z którego przyszedł akiecik a następnie wysyłając jakiś pakiecik trzeba wskazać do kogoś, a we write nie mamy jak tego podać

Przedstaw semantykę operacji recvfrom(2) i sendto(2).

recvfrom(2)
![](https://i.imgur.com/6yOABL3.png)
wkłada otrzymaną wiadomość do bufora, wzywający musi określić rozmiar bufora w len, jeśli src_addr nie jest NULL, wkłada się tam adres nadawcy wiadomości, adrrlen jest uaktualniane po powrocie by zawierało rzeczywisty rozmiar adresu źródłowego, jeśli dostarczony bufor jest zbyt mały, adres jest obcinany

sendto(2)
![](https://i.imgur.com/oUmC3g6.png)
no w sumie tak samo tylko w drugą stronę

Kiedy po stronie klienta następuje związanie gniazda UDP z adresem lokalnym?

wtedy kiedy użyjemy do tego binda :o szok


Jaki efekt przynosi wykonanie connect(2) na gnieździe klienta. Alternatywna (i poprawna odpowiedź brzmi) gdy nie wykorzystaliśmy bind jak bóg nakazał to podczas pierwszej operacji sendto występuję takie wiązanie, jest nawet error EAGAIN w sendto który mówi o tym, że nie udało się znaleźć wolnego portu ulotnego do związania

Na podstawie ... zreferuj efekt jaki przynosi wykonanie connect(2) na gnieździe klienta. Jakie ograniczeniapoprzednio wymienionych funkcji zostały poprawione przz wywołania recvmsg(2) i sendmsg(2)?

1. nie możemy już dłużej określać adresu ip celu i portu dla naszego outputu (no bo się z jakimś sconnectowaliśmy), więc nie używamy już sendto tylko write/send, wszystko jest wysyłane na adres określony podczas connect
2. analogicznie nie musimy używać recvFROM bo skoro mamy connect to wiemy FROM przychodzi (XD), zamiast tego używamy read, recv lub recvmsg
3. Błędy asynchroniczne są zwracane do procesu dla połączonych gniazd UDP - niestety nie wnikam co to dokładnie znaczy

Jakie ograniczenia poprzednio wymienionych funkcji zostały poprawione przez wywołania recvmsg(2) i sendmsg(2)?

1. Możesz zrobić bufory rozproszone/zbierane. Na przykład, powiedzmy, że chcesz otrzymać dokładnie 1MB danych, ale masz tylko 10 buforów, które mają po 100KB, to możesz wypełnić każdy w jednym wywołaniu recvmsg.
2. Dostęp do flag kontrolnych, danych pomocniczych i pól nagłówka pakietu IP. Na przykład, dla UDP, można uzyskać docelowy adres IP/portu, na który został zaadresowany pakiet poprzez wyliczenie danych kontrolnych (z włączonymi niektórymi ioctls) zwróconych z recvmsg.

No ogólnie są wydajniejsze, bo nie ma żadnych dodatkowych kopii pamięci, jak np wysyłane jest coś dużego w wielu pakietach, to można ominać nadmierne przetwarzenie headerów (jeśli dobrze rozumiem), a przy send nie trzeba czekać na przetworzenie headera (ok nie rozumiem chyba)


