„Sieci komputerowe” - laboratorium

Protokoły do realizacji

Protokół nr 1
Protokół nr 2
Errata do protokołu nr 2:

Zmodyfikowane terminy przesyłania programów

4 czerwca - dostarczenie interfejsu użytkownika
21 czerwca - dostarczenie końcowej wersji programu

Pytania i odpowiedzi

Co powinno składać się na interfejs?

Wszystko, co nie ma ścisłego związku z wykorzystywaniem protokołu. Interfejs powinien zapewniać obsługę logiki aukcji - zapamiętywanie wystawianych przedmiotów, zapamiętywanie zgłoszeń, zapamiętywanie najwyższej ceny... Akcje, które są zależne od użytkownika, w interfejsie będą kończyć się w pewnym momencie na jakichś funkcjach, które docelowo będą zaimplementowane w module obsługującym sieć, ale w pierwszym etapie raczej nic nie będą robiły. Tak więc w interfejsie będzie przykładowo wywołanie funkcji w rodzaju "zapoznaj się z aukcjami użytkownika X", ale chwilowo funkcja ta może wręcz nic nie robić. Oczywiście dla testów warto taką funkcję w jakiś prosty sposób zaimplementować, tak aby zwracała jakieś sztuczne dane - niepochodzące z sieci.

Interfejs to także ewentualne reakcje na zdarzenia płynące z sieci. I tutaj też początkowo oczekujemy, że póki mamy tylko interfejs, póty na przykład do przetestowania interfejsu te zdarzenia musimy wywoływać sztucznie. Jeżeli na przykład zrealizujemy w interfejsie funkcję reagującą na fakt, że ktoś chce dowiedzieć się czegoś o aukcjach, to docelowo funkcja ta powinna być wywoływana przez moduł obsługujący protokół. Póki ten moduł nie jest zrealizowany, w celu przetestowania programu jesteśmy zmuszeni sztucznie wywoływać tę funkcję z jakimiś fikcyjnymi danymi.

Czy można zaimplementować lekko zmienioną wersję któregoś z protokołów - korzystającą tylko z TCP?

Nie.

Dobrze się stało, że niezależnie od tego, który protokół Państwo wybiorą będą musieli Państwo realizować obsługę TCP jak i UDP. Dzięki temu Państwa programy nie będą banalne i podobne do siebie. Będą Pańswo musieli roztrzygać bardzo ciekawe problemy, które być może nie pojawią się już nigdy w Państwa karierze zawodowej, ale które mają duży wymiar edukacyjny - na przykład konstruowanie serwera, który jest jednocześnie serwerem TCP i UDP.

Będą Państwo musieli rozwiązać między innymi problem wysyłania dużych plików i już widać, że problem ten jest nierozwiązywalny w realizowanych przez Państwa protokołach. Ponieważ oba protokoły nie przewidują jakiejkolwiek segmentacji komunikatów, to programy powinny "mieć wiedzę" na temat ograniczeń protokołów i rezygnować z wysyłania zbyt dużych plików.

Protokół nr 2: w kanale informacyjnym (udp) sprzedający po wysłaniu szczegółów dotyczących przedmiotu czeka TIMEOUT na potwierdzenie od kupującego, czy ma mu wysłać załącznik, czy nie (w stanie ATTACHMENT_WAIT_STATE). Wydaje mi się to bez sensu - serwer zawiesza swoje działanie na długi czas z powodu jednego klienta i nie może obsługiwać żądań innych klientów.

Protokół nie zabrania obsługiwać żądań innych klientów. Co prawda protokół opisuje pewne stany w fazie informacyjnej, ale przebieg tych stanów jest unikalny dla danej pary serwer-klient (czy raczej nawet trójki serwer-klient-aukcja) i niezależny od obsługi innych klientów.

Potrzeba opisu jednoznacznej sytuacji za pomocą stanów - jednoznacznej dla calej aukcji i wszystkich licytujących - jest niezbędna jedynie w fazie licytacyjnej, aby zapewnić prawidłowy przebieg licytacji. W części informacyjnej natomiast, niezależne i równoległe prowadzenie wymiany informacji pomiędzy sprzedającym i kilkoma kupującymi nie zagraża utratą spójności wiedzy przez wszystkie strony.

Protokół nr 2: w kanale licytacyjnym (tcp) [...] gdy sprzedąjacy chce zakończyć aukcję, wysyła do wszystkich uczestników komunikat MSG_END, a następnie przechodzi do stanu CONFIRM_STATE w którym oczekuje na potwierdzenia od wszystkich użytkowników. Jednak w opisie perspektywy kupującego nie zostało przewidziane wysyłanie takiego komunikatu! Z diagramu i opisu wynika, że klient po otrzymaniu MSG_END natychmiast przechodzi do IDLE_STATE (nie wysyłając żadnego potwierdzenia).

Jest to nielogiczność w protokole, która na szczęście nie przeszkadza w implementacji, a nawet w sprawnym przebiegu aukcji! Serwer wyśle MSG_END, wszyscy się dowiedzą o końcu aukcji ale w żaden sposób nie zareagują, serwer nie dostanie potwierdzeń i w związku z tym wszystkich odłączy.

Protokół nr 2: rozważmy scenariusz, że sprzedający informuje wszystkich uczestników o nowej cenie i czeka na potwierdzenia w CONFIRM_STATE. Jeżeli w tym samym momencie użytkownik wyśle swoją nową ofertę, to przejdzie do stanu BID_CONFIRM_STATE i będzie czekał na potwierdzenie od serwera (czekają na siebie wzajemnie). Zgodnie z opisem protokołu, po upływie TIMEOUT sprzedajacy "przyjmuje, że licytujący zrezygnował z aukcji" i zostaje z niej wypisany (musi ponownie zgłaszać chęć uczestnictwa).

Taka sytuacja rzeczywiście może wystąpić, choć trudno oszacować, na ile jest prawdopodobna. Mimo to zaimplementujmy takie zachowanie serwera i klienta, aby mieć okazję naocznie przekonać się, jak często taka sytuacja będzie miała miejsce - myślę, że będzie to bardzo ciekawy eksperyment i praktyczna nauczka, aby protokołów w ten sposób nie pisać.

Protokół nr 2 nie wyjaśnia, jak ma zachować się klient, jeśli nie otrzyma potwierdzenia na swoją ofertę nowej ceny (w stanie BID_CONFIRM_STATE). Z opisu wynika, że po upływie TIMEOUT, po prostu "jak gdyby nigdy nic" wraca do stanu licytacji i może składać kolejne oferty.

Takie zachowanie klienta jest uzasadnione - fakt nieotrzymania potwierdzenia złożenia oferty jest pewną nieprawidłową sytuacją, i kupujący ma nawet prawo założyć, że ta oferta mogła nie dotrzeć do sprzedawcy. Aby nie pogarszać sytuacji kupujący mógłby zrealizować jakiś plan awaryjny - na przykład zrezygnować całkowicie z licytacji. Autor protokołu zaproponował natomiast udawanie, że żadnej oferty nie było - to jest całkiem dobry pomysł i takie rozwiązanie powiniśmy zaimplementować.


Ostatnia modyfikacja: 29 maja 2009