---
# System prepended metadata

title: Lista 9
tags: [SO]

---

# Lista 9
###### tags: `SO`

## Zadanie 1

Warstwy:

- łącza
przekierowuje przez serię routerów między źródłem a celem

- sieciowa


- transportowa
Transportuje wiadomości z warstwy aplikacji pomiędzy końcami aplikacji.




Protokoły warstwy łącza zajmują się komunikacją między urządzeniami w sieci lokalnej. Służą one do tworzenia połączenia między komputerami, urządzeniami sieciowymi i innymi urządzeniami podłączonymi do tej samej sieci. Protokoły te działają na fizycznym poziomie sieci i zapewniają wymianę danych między poszczególnymi urządzeniami.

Protokoły warstwy sieciowej zajmują się przesyłaniem danych pomiędzy różnymi sieciami. Służą one do tworzenia połączenia między różnymi sieciami, takimi jak sieć lokalna i internet, i zapewniają możliwość przesyłania danych między nimi. Protokoły warstwy sieciowej działają na poziomie sieci i zapewniają wymianę danych pomiędzy różnymi sieciami.

Protokoły warstwy transportowej zapewniają sprawną komunikację między aplikacjami i poszczególnymi hostami w sieci. Służą one do tworzenia połączenia między aplikacjami i zapewniają możliwość przesyłania danych pomiędzy nimi. Protokoły warstwy transportowej działają na poziomie transportu i zapewniają wymianę danych pomiędzy aplikacjami.




Protokoły warstwy łącza i sieciowej nie są używane do komunikacji między procesami użytkownika, ponieważ te protokoły działają na niższych poziomach modelu OSI i zajmują się przesyłaniem danych między urządzeniami w sieci. Komunikacja między procesami użytkownika jest zazwyczaj realizowana przez protokoły warstwy aplikacji, które działają na wyższym poziomie modelu OSI i umożliwiają bezpośrednią komunikację między aplikacjami.

## Zadanie 2

1. udp
- brak gwarancji dotarcia, kolejności i pojedynczego dotarcia
- brak automatycznej retransmisji
- każdy datagram ma długość, przekazywaną wraz z danymi
- strumień bajtów

2. tcp
- stałe połączenie między klientem a serwerem
- oczekuje potwierdzenia odbioru, retransmituje kilka razy przed poddaniem się
- sekwencjonuje dane

Półdupleks - dane mogą być przesyłane w obie strony, ale tylko w jednym kierunku jednocześnie.

Dupleks - dane mogą być przesyłane w obie strony jednocześnie

flow control - TCP mówi, ile bajtów może przyjąć na raz

## Zadanie 3

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

**W którym momencie następuje związanie gniazda z adresem lokalnym i zdalnym?**
Przy wywołaniu bind.

**Która ze stron komunikacji używa portów ulotnych (ang. ephemeral)?**
Obie.

**Co specyfikuje drugi argument wywołania systemowego listen(2)?**
Maksymalną długość kolejki oczekujących połączeń.

**Z jakim numerem portu jest związane gniazdo przekazywane do i zwracane z accept(2)?**
Z różnym. 

**Skąd serwer wie, że klient zakończył połączenie?**
Klient wysyła mu tą informację jako EOF.

## Zadanie 4

![](https://i.imgur.com/5Gtb7FL.png)

**Czemu, w przeciwieństwie do TCP, serwer może rozpocząć pracę zaraz po wykonaniu funkcji bind(2)?**
Ten protokół jest znacznie prostszy i nie potrzebuje stabilnego połączenia między klientem a serwerem, opiera się na pojedynczych wysyłanych danych.

**Z jakiej przyczyny interfejs read(2) i write(2) po stronie serwera może być niewystarczający?**
Potrafimy obsługiwać tylko jednego klienta na raz.

**Przedstaw semantykę operacji recvfrom(2) i sendto(2).**
Pierwsze odbiera wiadomość, drugie wysyła wiadomość.

**Kiedy po stronie klienta następuje związanie gniazda UDP z adresem lokalnym?**
W momencie wysłania danych.

**Na podstawie [7, 8.11] zreferuj efekt jaki przynosi wykonanie connect(2) na gnieździe klienta.**
Zapisanie adresu IP i numeru portu.
Nie możemy już używać `sendto` (ponieważ adres jest znany i ustalony)
Nie musimy używać `recvfrom`.

**Jakie ograniczenia poprzednio wymienionych funkcji zostały poprawione przez wywołania recvmsg(2) i sendmsg(2)?**
Dane mają teraz konkretniejszą strukturę.

## Zadanie 5



## Zadanie 6



## Zadanie 7



## Zadanie 8

```c=
#include "csapp.h"
#include "rio.h"

#define LISTENQ 10
#define MAXCLIENTS (PAGE_SIZE / sizeof(client_t))

typedef struct client {
  pid_t pid;    /* Client process id */
  size_t nread; /* Numer of bytes received so far */
} client_t;

/* TODO: Need to define context to be used with sigsetjmp & siglongjmp. */
static client_t *client = NULL;
static sig_atomic_t nclients = 0;
static size_t nread = 0; /* number of bytest received on all connections */
static jmp_buf env;

static client_t *findclient(pid_t pid) {
  for (int i = 0; i < MAXCLIENTS; i++)
    if (client[i].pid == pid)
      return &client[i];
  return NULL;
}

static client_t *addclient(void) {
  client_t *c = findclient(0);
  if (c) {
    c->pid = -1; /* XXX: must be filled in after fork */
    c->nread = 0;
    nclients++;
  }
  return c;
}

static void delclient(pid_t pid) {
  client_t *c = findclient(pid);
  assert(c != NULL);
  nread += c->nread;
  c->pid = 0;
  nclients--;
}

static void sigchld_handler(int sig) {
  pid_t pid;
  /* TODO: Delete clients as they die. */
  pid = Wait(NULL);
  safe_printf("[%d] Disconnected!\n", pid);
  delclient(pid);
  return;  
}

static void sigint_handler(int sig) {
  safe_printf("Server received quit request!\n");
  /* TODO: Change control flow so that it does not return to main loop. */
  siglongjmp(env, 0);
}

static void echo(client_t *c, int connfd) {
  size_t n;
  char buf[MAXLINE];
  rio_t rio;

  rio_readinitb(&rio, connfd);
  while ((n = Rio_readlineb(&rio, buf, MAXLINE))) {
    Rio_writen(connfd, buf, n);
    c->nread += n;
    /* XXX: Uncomment line below and watch client behaviour. */
    /* exit(0); */
  }
}

int main(int argc, char **argv) {
  if (argc != 2)
    app_error("usage: %s <port>\n", argv[0]);

  sigset_t sig_mask;
  sigemptyset(&sig_mask);
  sigaddset(&sig_mask, SIGCHLD);

  Signal(SIGCHLD, sigchld_handler);
  Signal(SIGINT, sigint_handler);

  client =
    Mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);

  int listenfd = Open_listenfd(argv[1], LISTENQ);

  /* TODO: Wait for all clients to quit and print a message with nread. */
  if (sigsetjmp(env, 1)) {
    while (nclients > 0) { }
    safe_printf("Server received %d bytes\n", nread);
    exit(EXIT_SUCCESS);
  }

  while (1) {
    socklen_t clientlen = sizeof(struct sockaddr_storage);
    struct sockaddr_storage clientaddr; /* Enough space for any address */
    int connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);

    static char client_hostname[MAXLINE], client_port[MAXLINE];
    Getnameinfo((SA *)&clientaddr, clientlen, client_hostname, MAXLINE,
                client_port, MAXLINE, 0);

    sigset_t mask;
    Sigprocmask(SIG_BLOCK, &sig_mask, &mask);

    /* TODO: Start client in subprocess, close unused file descriptors. */
    client_t *c = addclient();
    pid_t pid = Fork();
    if(pid) {
      // Parent
      Close(connfd);
    }
    else {
      // Child
      Close(listenfd);
      Signal(SIGINT, NULL);
      c->pid = getpid();
      echo(c, connfd);
      exit(EXIT_SUCCESS);
    }
    printf("[%d] Connected to %s:%s\n", pid, client_hostname, client_port);

    Sigprocmask(SIG_SETMASK, &mask, NULL);
  }
}

```
