...
MSG_BIDD{
uint13 version;
...
a powinno być:...
MSG_BIDD{
uint16 version;
...
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