L7: Ojciec Laurenty#

Werona — miasto pełne romantycznych tajemnic i skomplikowanych intryg. To właśnie tutaj rozegrała się tragiczna historia Romea i Julii — kochanków ze skłóconych rodzin. Po nieszczęśliwych wydarzeniach opisanych w filmie „Romeo + Julia" (1996), Ojciec Laurenty, mądry franciszkanin i spowiednik obojga kochanków, zaczął rozważać nowe metody komunikacji.

Zainspirowany osiągnięciami technicznymi XX wieku, Ojciec Laurenty postanowił użyć gniazd strumieniowych (SOCK_STREAM) do przesyłania wiadomości między kochankami ze skłóconych rodzin. Uznał, że ta nowoczesna forma komunikacji może być bardziej niezawodna i bezpieczna niż tradycyjne metody, takie jak posłańcy czy mnisi skradający się nocą.

Studenci Wydziału MiNI zostają powierzeni zadaniem pomocy Ojcu Laurentemu w stworzeniu niezawodnego serwera systemu komunikacji opartego na gniazdach strumieniowych i epoll, który umożliwiałby kontakt kochanków skazanych na rozłąkę z powodu nienawiści między ich rodzinami i zapewniałby bezpieczną wymianę informacji.

Ważne: Kompletne wiadomości (w tym zawierające imiona) w całym zadaniu zawsze kończą się znakiem nowej linii \n. Żadna wiadomość od klienta (łącznie z \n) nie może przekraczać MAX_MSG_LEN.

Poniżej wymienieni są klienci, którzy mogą łączyć się z serwerem. Wszyscy, z wyjątkiem base_client.sh, czekają określoną liczbę (domyślnie 1) sekund przed wysłaniem każdej wiadomości; po wysłaniu ostatniej wiadomości netcat czeka dwa razy dłużej przed zamknięciem połączenia.

  • Klient podstawowy: łączy netcat z gniazdem UNIX Laurenty (stała UNIX_SK_NAME w kodzie) i poprzedza każdą wypisaną linię swoją nazwą, nie wysyła wiadomości samodzielnie.
    ./base_client.sh [name] [netcat args]
  • Klient czekający i wysyłający jedną niekompletną wiadomość (swoje imię):
    ./intr_client.sh <name> <beloved> [seconds between messages]
  • Klient wysyłający jedną kompletną (imię) i jedną niekompletną wiadomość (imię ukochanej/ukochanego):
    ./intr_client2.sh <name> <beloved> [seconds between messages]
  • Klient wysyłający poprawnie oba imiona:
    ./named_client.sh <name> <beloved> [seconds between messages]
  • Klienci wysyłający poprawnie oba imiona i kilka dodatkowych wiadomości:
    ./[chatty_client.sh | happy_client.sh] <name> <beloved> [seconds between messages]

Etapy:#

Etap 1 (5 pkt)#

Ojciec Laurenty chce oszacować, ile młodych ludzi potrzebuje jego pomocy w przekazywaniu tajnych wiadomości miłosnych. Utwórz gniazdo strumieniowe typu UNIX. Użyj mechanizmu epoll, poll lub select do nasłuchiwania przychodzących połączeń od klientów. Po nawiązaniu połączenia wypisz “Another young person ([descriptor]) needs my help!” i zamknij połączenie.

Program przyjmuje jeden argument: liczbę sekund od ostatnio zaakceptowanego połączenia, po której serwer przestaje nasłuchiwać, wypisuje “No one needs my help anymore!”, zwalnia wszystkie zasoby i kończy działanie.

Przed zakończeniem programu usuń dowiązanie do gniazda UNIX z systemu plików. Nie pozostawiaj śladów swojej działalności w Weronie!

Przykładowy test: ./base_client.sh

Etap 2 (8 pkt)#

Przyjmuj deklaracje miłości od osób, które chcą pójść w ślady słynnych kochanków. W pierwszej wiadomości klient podaje swoje imię, a w następnej — imię ukochanej/ukochanego. Po uzupełnieniu obu pól wypisz "[client name] wants to marry [beloved name]" i zamknij połączenie. Możesz założyć, że jedno imię nie będzie użyte wielokrotnie.

Użyj mechanizmu multipleksowania dodanego w pierwszym etapie do oczekiwania na wiadomości. Tym razem Ojciec Laurenty czeka timeout sekund zarówno na przychodzące połączenia, jak i wiadomości od klientów przed zakończeniem działania.

Jeśli klient rozłączy się przed podaniem obu imion, wypisz “I lost contact with [client name]”. Jeśli klientowi nie udało się podać własnego imienia, użyj wyraźnego ciągu zastępczego, np. "??".

Przykładowe testy:

  • ./named_client.sh Julia Romeo
  • ./intr_client.sh Romeo Julia
  • ./intr_client2.sh Walencjo Sylwia

Etap 3 (6 pkt)#

Po uzyskaniu obu imion od klienta, spróbuj znaleźć jego ukochaną/ukochanego wśród innych klientów poprzez porównanie imion klientów i imion ukochanych. W przypadku sukcesu wypisz "[client name] and [beloved name] got married!", następnie wyślij wiadomość “Congratulations, [client name] and [beloved name]!” do obojga, zamknij oba połączenia i zwolnij powiązane zasoby. Wysyłany ciąg może być taki sam dla obojga. Jeśli nie można znaleźć pary, kontynuuj działanie programu bez zmian.

Przykładowy test: ./named_client.sh Julia Romeo & ./named_client.sh Romeo Julia

Etap 4 (5 pkt)#

W Weronie młode pary są zmuszone trzymać swoją miłość w tajemnicy przed rodzinami. Ojciec Laurenty działa jako pośrednik, przekazując wiadomości między kochankami. Gdy serwer odbierze kompletną wiadomość (zakończoną znakiem nowej linii) od klienta, jego zadaniem jest wysłanie jej do partnera. Jeśli nie ma partnera, wiadomość jest odrzucana.

Przykładowy test: ./happy_client.sh Julia Romeo & ./chatty_client.sh Romeo Julia

Czasem Ojciec Laurenty znajduje wiadomości bez podpisu, ale z adresatem. Przekazuje je również. W programie nasłuchuj (w epoll) również na standardowym wejściu wiadomości w formacie <addressee>:<message> i przekazuj je do odpowiedniego adresata. W przypadku nieprawidłowego adresata lub linii w złym formacie, zignoruj ją i wypisz odpowiedni komunikat o błędzie.

Kod startowy#