4. Systemy rozproszone

4.8. Java jako programowa platforma dla systemu rozproszonego

Szybki rozwój technik internetowych i zastosowań technologii sieciowych powoduje rosnące zainteresowanie rozproszonymi systemami pomiarowymi. Problemy w zakresie projektowania rozproszonych systemów pomiarowych wiążą się głównie ze stosowanymi technologiami sieciowymi i złożonością ich oprogramowania. W aspekcie technologii sieciowych, wymagane jest zastosowanie architektury otwartej współpracującej z wieloma różnymi wirtualnymi przyrządami pomiarowymi czy podsystemami, gwarantującej deterministyczny charakter transmisji. Natomiast w aspekcie oprogramowania, głównym problemem jest to, że konwencjonalne techniki tworzenia programów zawodzą w przypadku rozproszonych i złożonych systemów. Dzieje się tak za przyczyną długiego czasu tworzenia aplikacji sieciowych i wysokich kosztów z tym związanych.

Z pomocą przychodzi programowanie zorientowane obiektowo. Technika ta ułatwia tworzenie oprogramowania systemowego poprzez zbiór współpracujących ze sobą, niezależnych elementów - obiektów. Obiekty mogą być rzeczywistymi bądź też wirtualnymi przyrządami, sterownikami urządzeń, serwerami, klientami, lub wreszcie abstrakcyjnymi obiektami jak funkcje matematyczne i logiczne.

Językiem umożliwiającym sieciowe programowanie obiektowe jest Java, opracowana przez informatyków z Sun Microsystems. Język ten ułatwia modularne programowanie oraz pozwala na wielokrotne wykorzystywanie kodu, w sposób efektywny i nieskomplikowany. Zapewnia on ścisłą kontrolę typów, ma automatyczne zarządzanie pamięcią, wbudowane wątki oraz wygodne w użyciu biblioteki klas programowania sieciowego. Programy kompilowane są do formatu pośredniego, niezależnego od rodzaju komputera i systemu operacyjnego (platformy informatycznej). Pozwala to na wykonywanie skompilowanych programów w dowolnej architekturze sprzętowej, dla której jest dostępny interpreter Javy, a więc również na dowolnych komputerach osobistych i stacjach roboczych.

Związana z Javą technologia apletów ożywiła strony Internetowe. Aplety to wykonywalny kod Javy, ładowany wraz ze stronami HTML. Architektura Javy zapewnia to, że aplety nie mogą wykonywać niepożądanych, ze względu na bezpieczeństwo, operacji na komputerze użytkownika (np. otwierania plików). Aplety Javy doskonale nadają się do wzbogacania podręczników elektronicznych przygotowywanych w formacie HTML.

Szybko rośnie liczba aplikacji napisanych w Javie. Pojawiło się sporo związanych z nią technologii, takich jak rozproszone obiekty Javy, dostęp do baz danych przez Javę, klasy do kodowania danych czy wreszcie JavaOS (system operacyjny napisany w Javie).

 

Java a programowanie klient-serwer

Podczas tworzenia aplikacji typu klient-serwer w Javie z reguły wykorzystuje się połączenia sieciowe przez tzw. gniazdka (ang. sockets) za pomocą standardowej biblioteki java.net. Posługiwanie się umieszczonymi tam klasami wymaga obsługi wyjątków Javy. Wygodniejszy dostęp do gniazdka zapewniają standardowe klasy strumieni wejścia i wyjścia (InputStream/OutputStream). Ponadto, dość często wykorzystywane są wątki - po stronie klienta do zapewnienia asynchronicznego odbioru danych z serwera, a po stronie serwera do jednoczesnej obsługi zadań pochodzących od wielu klientów.

Jak już wspomniano wcześniej, gniazdka to dostępna na wielu systemach unixowych oraz pod Windows metoda komunikacji sieciowej miedzy programami. Gniazdko należy traktować jako kanał komunikacyjny, gdzie jeden program wpisuje do niego dane w postaci strumienia bajtów, a drugi je odbiera. W celu nawiązania połączenia, jeden z programów (serwer) musi otworzyć gniazdko i oczekiwać na połączenie. Z otwartym gniazdkiem musi być związany pewien numer, zwany portem. Program łączący się z otwartym gniazdkiem (klient) musi znać sieciowy adres komputera (IP) oraz numer portu. Wiele serwisów, np. telnet, ftp, gopher czy www, ma przydzielone na sztywno i ogólnie znane porty. Użytkownicy niestandardowych programów muszą sami zadbać o to, żeby numer portu serwera był znany klientom. Program, który otworzył gniazdko może, ale nie musi zaakceptować połączenia.

Gniazdka są łączem dwustronnym - oznacza to, że do otwartego gniazdka dane można zarówno wpisać, jak i odczytać. Tak, więc dla dwustronnej komunikacji między programami wystarczy otwarcie tylko jednego gniazdka. W modelu klient/serwer implementowanym w Javie typowe jest używanie dwóch rodzajów gniazdek, pochodzących ze standardowej biblioteki java.net:Socket oraz ServerSocket. Klasa Socket wykorzystywana jest przez klienta - wystarczy podanie adresu internetowego oraz portu, aby połączyć się z działającym serwerem. Obsługa połączeń jest nieco bardziej skomplikowana od strony serwera, który używa klasy ServerSocket. ServerSocket czeka na nadchodzące połączenia od klientów. W chwili odebrania żądania połączenia ServerSocket tworzy nowy obiekt typu Socket, dzięki któremu serwer może porozumiewać się z klientem. W tej sytuacji zarówno klient, jak i serwer mają dostęp do własnych, lokalnych kopii obiektu Socket, dzięki którym mogą się porozumiewać ze sobą. Dodatkowo, ServerSocket może akceptować dalsze połączenia od klientów, co oznacza, że wielu klientów może jednocześnie mieć otwarte połączenia z tym samym serwerem.

Możliwość jednoczesnej obsługi wielu klientów oznacza, że gdy np. żądanie jednego z nich wymaga czasochłonnego dostępu do dysku, serwer może przydzielić czas procesora innemu klientowi. W przeciwnym wypadku, gdy obsługiwany jest tylko jeden klient, serwer czeka na zakończenie dostępu do dysku i marnuje czas procesora (lub wielu procesorów - gdy serwer działa na wieloprocesorowym komputerze).

 

Wątki w Javie

Popularnym narzędziem Javy jest wątek. Wątek można traktować jako część programu wykonywaną współbieżnie w obrębie danego procesu. Jeden proces może zawierać wiele wątków, mających dostęp do wspólnych danych. Wiele implementacji wątków współdziała z operacjami wejścia/wyjścia, dzięki czemu gdy jeden wątek zablokowany jest na przykład operacją czytania z konsoli lub z dysku, inny jest automatycznie uruchamiany.

Możliwe jest kontrolowanie porządku wykonywania wątków przez związanie z nimi priorytetów. Wykonywanie wątków może być przeplatane w czasie, podobnie jak wykonywanie procesów w systemie operacyjnym, z podziałem czasu. Twórcy Javy bardzo starannie zaprojektowali wątki - są one łatwe i wygodne w użyciu. W serwerze umożliwiają jednoczesną obsługę wielu klientów (odbieranie wielu połączeń i przypisywanie każdemu połączeniu osobnego wątku). Natomiast w przypadku klienta jeden wątek będzie czytał dane pochodzące od serwera, a inny np. wyświetlał nadchodzące dane czasu rzeczywistego.

 

Wyjątki w Javie

Podczas wykonywania programu może zajść wiele niespodziewanych sytuacji. Niektóre wydarzenia można przewidzieć - na przykład to, że komputer z serwerem przestanie działać albo, że niedostępne będzie połączenie miedzy dwoma komputerami przez sieć. Są też inne sytuacje, uniemożliwiające połączenie się z serwerem klasyfikowane jako nieprzewidywalne - na przykład błąd w kodzie protokołów sieciowych, objawiający się w dość przypadkowy sposób okresową niemożliwością wysyłania pakietów.

Java zapewnia mechanizm obsługi sytuacji wyjątkowych, który wykorzystuje się do uodpornienia kodu klienta na niepożądane zdarzenia. Mechanizm ten działa na takiej zasadzie, że sytuacje wyjątkowe komunikowane są przez stworzenie obiektu z informacją o wyjątku. Procedury, w których mogą powstać sytuacje wyjątkowe (jak na przykład próba odczytu nieistniejącego pliku czy próba połączenia przez sieć z nieczynnym przyrządem wirtualnym), muszą deklarować rodzaje wyjątków jakie mogą wystąpić.