portal Michała Hanćkowiaka
Begin main content
Search · Index
No registered users in community Materiały
in last 10 minutes

ALR - ćw - temat C

Materiały o j. Tcl

Gniazdka i programowanie zdarzeniowe w j. Tcl

Prosty sposób na implementowanie algorytmów asynchronicznych w realnym świecie...

Przychodzące komunikaty są obsługiwane przez "handler zdarzeń" (stąd programowanie zdarzeniowe).

Jak to się ma do teoretycznego modelu obliczeń?
program (interp tcl-a) = węzeł grafu kom,
połączenie TCP = krawędź grafu kom,
wykonanie handlera = zdarzenie obliczeniowe.

Prosty przykład użycia gniazdek (zakłada się, że komunikat to linia tekstu zakończona znakiem \n).
## klient
#
set host "localhost"
set s [socket $host 10000]
# tworzymy połączenie tcp z serwerem na maszynie $host, port=10000
# komenda socket zwraca gniazdko repr. koniec tego połączenia

puts $s "A ku ku !!!"
# wysylamy dane przez gniazdko s
flush $s
# flush to wypróżnienie buforów
# !!! bardzo ważne bez tego dane nie zostaną "wypchnięte" !!!

close $s
## serwer # socket -server obsluga 10000 proc obsluga {s args} { fileevent $s readable "obslugaKli $s" # dla każdego zgłaszającego się klienta definiujemy # obsługę zdarzenia "readable" na gniazdku tego klienta ... # uwaga: jeśli można odczytać 1 znak to można odczytać cały komunikat! } proc obslugaKli s { if {[eof $s]} { close $s; return } # "eof" pojawi się dokładnie wtedy, gdy klient zamknie gniazdko! # wtedy po stronie serwera usuwamy zasoby związane z tym klientem set linia [gets $s] puts $s "odp na: $linia" flush $s } # wersja obslugaKli z tzw. "zmiennymi sesyjnymi" proc obslugaKli s { upvar ::dane,$s dane; # tabl. dane to zm. sesyjne... if {[eof $s]} { close $s; unset -nocomplain dane; return } # zm. sesyjne są automatycznie usuwane, gdy klient się odłączy set linia [gets $s] lappend dane(linie) $linia; # np. zapamiętujemy linie, które przysłano puts $s "odp na: $linia" flush $s }

Objaśnienie operacji I/O w j. Tcl: Tcl_io_tutorial
patrz też Tcl_net_idioms (uwagi praktyczne o budowaniu serwerów zdarzeniowych w j. Tcl)

Jak programować algorytmy asynchroniczne/zdarzeniowe w praktyce? (w j. Tcl)

"Handler" to procedura obsługująca przychodzące komunikaty/ zdarzenia.
Większe problemy (programistyczne) zaczynają się, gdy handler musi czekać na inne komunikaty.
Możliwe rozwiązania:
1. tylko handler
- jeśli handler potrzebuje innego komunikatu to musimy go rozbić na dwa...
- niskopoziomowe programowanie! (klasyczna maszyna stanowa)
- handler (proc) zawsze wykonuje się w 100%, tj od początku do końca
2. handler + vwait
- handler czeka na inny komunikat przy pomocy "vwait zmienna"
- nie można zagnieżdżać vwait-ów/ pętli zdarzeń !!! (...)
3. handler w wątku/fiberze/coroutinie
- gdy handler czeka na komunikat to robi yield (usypia się) i jest budzony gdy ten komunikat się pojawi
- to jest najogólniejsze rozwiązanie...



Zadanie 40 (inż.)(2.5pkt) "czat audio"
Chodzi o możliwość przekazywania strumienia audio między użytkownikami
w trybie halfduplex (tzn jeden nadaje - wielu słucha).
Obsługę dzwięku dostarcza pakiet "snack", jednak w tym zadaniu nie trzeba go używać;
chodzi tylko o to aby zapewnić, że w danej chwili "jeden nadaje a wielu słucha",
przy czym WYMAGA się aby cały czas była spełniona "zasada X":
    jeśli istnieje słuchający to musi istnieć nadający.
       (zasada ta wynika ze specyficznych cech pakietu snack...)
Oprogramowanie klienta powinno zawierać guzik "chcę nadawać",
który jest zielony gdy możemy mówić i czerwony gdy słuchamy...
Wymyśl sposób na sprawdzenie czy Twoje rozwiązanie jest poprawne!
np. "log" z zapisem zmiany stanu klientów, z b. dokładnym czasem zdarzenia,
tworzony przez klientów, plus skrypt sprawdzający czy wszystko ok ?!?!


Zadanie 40a (inż.)(1.5pkt) "czat audio (błędny)"
Pokaż, że Twój sposób sprawdzania poprawności z.40
wykaże błąd w błędnym rozwiązaniu...

Zadanie 40b (inż.)(1.5pkt) "send/recv dla j. Tcl (lub innego)"
Zaprogramuj prawidłowe proc do wysyłania/odbierania komunikatów,
proc send {sock msg} {...}
proc recv {sock} {...}
które będą działały poprawnie w następujących warunkach:
1 wątek, 1 konsola, tryb nieblokujący w obu proc,
dowolnie długie komunikaty z dowolnymi znakami,
odporność na ataki przez fałszywy format komunikatu,
brak ryzyka zakleszczenia...
Oprócz proc należy podać przykład ich zastosowania, jak w przykładach wyżej,
w szczególności sprawdzić czy przy długich kom jest ok...
Opisać także format komunikatu używany przez proc.

Messaging, MOM, "ZeroMQ", ...

MOM = Message Oriented Middleware

Inne niż ZeroMQ oprogramowanie/prot typu MOM:
RabbitMQ, qpid, AMQP, JMS (Java), stomp, Kafka, ActiveMQ, MQTT, ...

ZeroMQ (zeromq.org) to biblioteka typu "super gniazda" ...
książka: zguide.zeromq.org (zguide), spec: dokumenty RFC,
api docs: api.zeromq.org/4-1, api.zeromq.org/3-0, api.zeromq.org/2-0
(widać różnice między wersjami!)

Uwagi o ZeroMQ (ZMQ):

  1. komunikacja i sposób serializowania str. danych są całkowicie rozdzielone,
    można serializować textowo i binarnie na różne sposoby...
    ser. txt. : XML (wiele std.; SOAP, JAXB), JSON, YAML, ...
    ser. bin. : msgpack, protobuf (google?), thrift, CDR z Corby, ...
  2. istnieje wiele wzorców komunikacji, np. REQ/REP, PUB/SUB, ...
    zmq wymusza prawidłowe posługiwanie sie met. send/recv w danym wzorcu!
    niektóre wzorce pozwalają na wysyłanie do wielu odbiorców (subskrybentów)
  3. gniazdko ZMQ może mieć wiele połączeń!
    tzn. można wielokrotnie wywołać met. connect na tym samym gniazdku! (zastosowania? patrz niżej)
    tradycjne gniazda (BSD) maja tylko 1 połączenie, dlatego na serewerze jest ich wiele...
  4. komunikaty mogą być wieloczęściowe!
    w niektórych częściach umieszcza się "dane techniczne" np. adr. nadawcy
  5. gniazdko ZMQ ma typ: REQ, REP, ROUTER, DEALER, ...
    typ określa jak działają metody send/recv na tym gniazdku;
    niekiedy metody te dodają/usuwają części komuniktu (jakby nagłówki);
    jak działaja gniazdka typu ROUTER? patrz zguide, chapter 3;
    w manualu zmq_socket() jest krótki opis wszystkich typów gniazdek...
  6. są dwa zasadnicze wzorce komunikacyjne: REQ/REP i PUB/SUB,
    REQ/REP coś jak RPC, klient wysyła pytanie, serwer je odbiera, wysyła odp, klient odbiera odp;
    PUB/SUB działa jak "multicasting"; pub wysyła komunikat do wszystkich sub (subskrybentów);
    subskrybenci muszą podać "temat" ktory ich interesuje (jest to prefix komunikatu!),
    temat moze być też w pierwszej części wieloczęsciowego komunikatu!
  7. jeśli gniazdko REQ klienta jest podłączone do wielu gniazdek REP serwerów,
    to komunikaty jest wysyłany cyklicznie do kolejnych serwerów (RoundRobin),
    jest to prymitywna metoda zapewniania load balancing-u...
  8. oba wz. kom. REQ/REP i PUB/SUB występuja też w wersji z "proxy";
    REQ/ROUTER+DEALER/REP, proxy zawiera 2 gniazdka o typach ROUTER i DEALER
    PUB/XSUB+XPUB/SUB, proxy zawiera 2 gniazdka o typach XSUB i XPUB;
    usługę proxy można realizować jedną komendą "zmq proxy s_we s_wy" (w impl. tcl-owej ZMQ)
  9. inne wz. kom.: PUSH/PULL, ???, ...

Oprogramowanie ZeroMQ oraz przykłady w j. Tcl:
zeromq.zip (z sodium) zawiera pkg tcl-a (lin32), wymaga tcl8.6, folder z przykładami
PRZED uruchomieniem konsoli uruchomić skrypt ". ./e" !!
docs dla tcl/zmq: zmq w tcl (wiki), msgpack w tcl (serializacja binarna), slajdy pomocnicze

## ZeroMQ - serwer, wzorzec REQ/REP
#
lappend auto_path ./zeromq
package re zmq
  #% 4.0.1
package re msgpack
  #% 0.5.0

zmq context c1
zmq socket s1 c1 REP
  #% ::s1

s1 bind "tcp://*:7777"

s1 readable qqq
  # + callback serwerowy, automatycznie odp. klientom...
proc qqq args {
  set x [s1 recv]
  puts "args=$args, x=$x"
  s1 send "odp na: $x"; # odp jest niezbedna w REP/REQ !
}

vwait qqq

s1 destroy
c1 destroy


## ZeroMQ - klient, wzorzec REQ/REP
#
lappend auto_path ./zeromq
package re zmq
  #% 4.0.1
package re msgpack
  #% 0.5.0

zmq context c1
zmq socket s1 c1 REQ
  #% ::s1

s1 connect "tcp://localhost:7777"

s1 send "A ku ku !!! ???"
s1 recv
  #% odp na: A ku ku !!! ???
  # + zmq WYMUSZA odp. kolejnosc send/recv 
  #   zgodna ze wzorcem komunikacjyjnym (REQ/REP w tym przypadku)

c1 config
s1 config
  # + introspekcja?

s1 destroy
c1 destroy

Uwaga, 14.06.2021: w zadaniach o ZMQ można używać innej nakładki na bibl zmq, niż tcl-owa...

Zadanie 41a "eksperyment z ZeroMQ w j. Tcl, wzorce komunikacyjne"
Proszę rozbudować powyższy przykład, tak aby przetestować
TRZY różne wzorce komunikacyjne (nie tylko REQ/REP, patrz docs...).
Proszę także opisać własnymi słowami działanie każdego z wzorców komunikacyjnych!

Zadanie 41b "eksperyment z ZeroMQ w j. Tcl i innych"
Proszę rozbudować powyższy przykład, tak aby:
1. były używane 2 różne języki programowania (Tcl + jakiś inny),
2. powinny współpracować programy w różnych j. prog.

Zadanie 42 "ZeroMQ + serializacja BINARNA"
Stworzyć przykład z wzorcem REQ/REP bibl. ZeroMQ, w którym przesyła się
zbiór (dowolnej mocy) macierzy oznaczonych przez etykiety txt,
macierze mają dowolne wymiary;
dane maja być serializowane binarnie;
serwer powinien zwrócic macierze przemnożone przez stały współczynnik.
Propozycja (kontrowersyjna): do serializacji binarnej użyć CDR z Corby;
w plikach "cdr*.tcl" w tym folderze są przykłady jak wyciągnąć CDR z
Combata (broker Corby j. Tcl) i JavaIDL (broker Corby j. Java).
10.05.2021: Combat działa jedynie z tclkit8.6b1 (z uwagi na wersje Itcl 3.0)

Zadanie 43 "ZeroMQ + proxy"
Zbuduj przykład używający procesu proxy do którego podłączają się
zarówno klienci jak i serwery.
Użyj gniazdek REQ dla klientów, REP dla serwerów, ROUTER|DEALER dla proxy.
W takim układzie żądania klientów będą "równomiernie rozkładane" pośród serwerów.
Na 1 żądanie klienta przypada jedna odpowiedź od serwera (który został wybrany do obsługi tego klienta).

Zadanie 44 (1.5pkt) "ZeroMQ + proxy, inny wzorzec komunikacji"
Zrób to samo co w zadaniu poprzednim, z tą różnicą, że:
na 1 żądanie klienta przypada wiele (nie wiadomo ile) odpowiedzi serwera;
ostatnia odpowiedź jest specjalnie oznaczona;
Wskazówka: Da się to zrobić przy pomocy gniazdek DEALER/ROUTER,
oraz drobnych modyfikacji komunikatów, czytaj chapter 3 i zmq_socket()

Zadanie 45 "ZeroMQ + security"
Zbadaj jak działają zabezpieczenia typu "PLAIN" w ZMQ, analizując przykłady alr_zmq03* z folderu,
oraz dokumentację w nich zawartą (w alr_zmq03kli.tcl); patrz także api doc...
Opisz własnymi słowami jak to wszystko działa,
oraz jak klient może się przekonać, że podał złe hasło(!).

Zadanie 46 (1.5pkt) "ZeroMQ + security c.d."
Zbuduj przykład podobny do tego z poprzedniego zadania,
ale tym razem dla mechanizmu "CURVE" (wymaga wersji zmq z sodium !!).
Ten mechanizm umożliwia szyfrowanie kom. a każdy węzeł ma parę kluczy (pub/priv).
Klucze pub pozwalają uwierzytelniać przeciwną stronę.
Wskazówki: Jak się konfiguruje ten mechanizm?? Patrz dokumenty i blogi z alr_zmq03kli.tcl,
w szczególności blog 45 (The ZeroMQ Security API) oraz zmq_curve.
Nie wiadomo jak są zakodowane "credentials" w proc www na ser (kodowanie z85 ?) - zbadaj to.
Sprawdź programem wireshark czy komunikaty rzeczywiście są zaszyfrowane - wklej dowód.
Zbadaj co się dzieje jeśli podać wadliwe klucze - opisz efekty.
Zbadaj co się dzieje jeśli klucze są ok, ale kli został odrzucony przez ser (proc www na ser).

Zadanie 46a "ZeroMQ + security vs proxy"
Zbadaj czy bezpieczne połączenie (patrz Z.46) możę przechodzić przez proxy,
np. REQ -> ROUTER|DEALER -> REP, gdzie ser REP uwierzytelnia kli REQ

Zadanie 47 "ZeroMQ + REQ/REP vs kill"
Mamy gniazdko s1 typu REQ podłączone do 3 gniazdek REP, w 3 osobnych procesach;
wykonujemy operacje: s1 send "a ku ku"; s1 recv
w odp powinien być nr portu i pid procesu/serwera z gniazdkiem REP;
co się stanie jeśli zabić jeden z serwerów?
jeśli jest problem (blokada?) to jak temu przeciwdziałać?
wymień wszystkie możliwości, m.in związane z poll i zamianą REQ na coś innego;
weź też pod uwagę restartowanie serwera z tym samym nr portu...

Zadanie 47a "ZeroMQ + PUB/SUB vs kill"
odpowiednik zadania 47, ale dla wzorca komunikacyjnego PUB/SUB

Zadanie 48 (1.5pkt) "ZeroMQ + gubienie pakietów"
Zbadaj kiedy ZMQ gubi pakiety; przeanalizuj następujące "architektury":
1. PUSH -> PULL,
2. PUB -> SUB,
3. PUB -> XSUB|XPUB -> SUB;
Wymyśl sposób na obronę przed tym zjawiskiem w przypadku (2) i (3).
Wskazówka: zajrzyj do odp rozdziału zguide...;
Potrzebne pojęcia: HWM = High Water Mark (param config socketu)

uwaga: portal używa ciasteczek tylko do obsługi tzw. sesji...