RPC

Prosta aplikacja klienta

  1. Pobranie implementacji serwera: rtime.tar
  2. Skompilowanie i uruchomienie serwera.
  3. Sprawdzenie listy zarejestrowanych programów RPC:
    /usr/sbin/rpcinfo -p
  4. Implementacja klienta pobierającego aktualny czas (po stronie serwera). Wykorzystanie funkcji:
    int callrpc(char *host, unsigned long prognum,
                     unsigned long versnum, unsigned long procnum,
                     xdrproc_t inproc, char *in,
                     xdrproc_t outproc, char *out);
    zadeklarowanej w pliku nagłówkowym:
    rpc/rpc.h
    Numery programu i procedury pobrać można z pliku nagłówkowego:
    rtime.h
    gdzie zdefiniowane są stałe:
    TIMEPROG
    TIMEVER_1 
    get_time
    Procedura get_time nie wymaga parametrów wejściowych (xdr_void), a jako wynik (parametr out) zwraca zmienną int (xdr_int) oznaczającą liczbę zalogowanych użytkowników.
  5. Kompilacja programu klienta:
    gcc -o rtime_client rtime_client.c

Usługa zdalnego zabijania procesów

Zadanie: napisać aplikację (serwer+klient) umożliwiającą zdalne zabijanie procesów. Klient ma uruchamiać zdalną procedurę, która jako parametr przyjmuje PID procesu do zabicia. Procedura zdalna jako wynik zwraca int określający status zakończenia operacji (0 - proces został unicestwiony, -1 - wystąpił błąd)

  1. Utworzenie pliku rkill.x z opisem usługi:
    program RKILL_PROG {
      version RKILL_VERS_1 {
        int rkill(int pid) = 1;
      } = 1;
    } = 0x22000000;
  2. Wygenerowanie części kodu programem:
    rpcgen -a -N rkill.x
    Program wygeneruje następujące pliki:
    rkill.h          - plik nagłówkowy z definicjami stałych
    rkill_client.c   - szkielet aplikacji klienta
    rkill_server.c   - szkielet aplikacji serwera
    rkill_clnt.c     - stub klienta
    rkill_svc.c      - stub serwera
    Makefile.rkill
  3. Kompilacja z wykorzystaniem Makefile:
    make -f Makefile.rkill
  4. Implementajca zabijania procesu w pliku rkill_server.c z wykorzystaniem funkcji:
    int kill(pid_t pid, int sig)  (man 2 kill)
  5. Dodanie wyświetlania statusu wykonania po stronie klienta (plik rkill_clietn.c)
  6. Dodanie drugiego argumentu dla zdalnej procedury: numer wysyłanego sygnału
    • zmiana definicji w pliku rkill.x:
      int rkill(int pid, int signum) = 1;
    • ponowne wygenerowanie kodu programem rpcgen
    • implementajca funkcjonalności serwera i klienta
  7. Dodanie procedury echo, która pozwala na wypisanie po stronie serwera tekstu przesłanego przez klienta
  8. Przetestowanie działania mechanizmu timeout poprzez:
    • zabicie serwera
    • opóźnienie wysłania odpowiedzi przez serwer przy użyciu funkcji:
      unsigned int sleep(unsigned int seconds);
      test dla komunikacji po udp oraz po tcp
  9. Ustawianie timeout dla klienta:
    • modyfikacja stałej:
      TIMEOUT
      zdefiniowanej w pliku
      rkill_clnt.c
    • wykorzystanie funkcji:
      bool_t clnt_control(CLIENT *cl, int req, char *info);
      req = CLSET_TIMEOUT - ustawianie wartości timeout
      req = CLSET_RETRY_TIMEOUT - ustawianie czasu dla ponawiania żądania (tylko UDP)
      Przykład:
      struct timeval tm = { 60, 0 };
      clnt = clnt_create (host, RKILL_PROG, RKILL_VERS_1, "udp");
      clnt_control(clnt, CLSET_TIMEOUT, &tm);

Wywołanie asynchroniczne

Zadanie: Zmodyfikować rkill tak, aby klient mógł kontynuować przetwarzanie bez oczekiwania na zakończenie obliczeń przez serwer (zakładamy, że klienta nie interesuje odpowiedź od serwera)