Projektowanie i wytwarzanie aplikacji internetowych (część 2)

Sebastian Wyrwał

Kontynuując rozważania nad projektowaniem i wytwarzaniem
aplikacji internetowych należy zdać sobie sprawę z podziału inżynierii
oprogramowania na część związaną z zagadnieniami technicznymi (tutaj dotyczącymi
komunikacji) i część związaną ze specyfikacjami. (Informatyka
uniwersytecka, z teorią algorytmu, złożonością obliczeniową, pozostaje w
ogóle poza naszym zainteresowaniem.) Z jednej strony specyfikacja jest
fundamentem dla technologii, bez niej nie było by konkretnych rozwiązań, z
drugiej strony dąży się do tego aby w procesie projektowania, tak długo jak
można, abstrahować od konkretnych technologii i narzędzi. Informatyka staje
się więc po trosze nauką o specyfikacjach. Mogą one stanowić uogólnienie
rozwiązań technicznych. Celem specyfikacji jest ujednolicenie rozwiązań,
uczynienie ich bardziej niezawodnymi i czytelnymi. Specyfikacje są szczególnie
istotne tam, gdzie trzeba zapewnić poprawną współpracę składników
tworzonych przez różnych producentów. Sytuacja taka ma miejsce w systemach
rozproszonych.


RM-ODP i Model obiektowy

Przyczyną powstania modelu RM-ODP był szybki wzrost
popularności przetwarzania rozproszonego, który zaowocował koniecznością
wprowadzenia dla niego standaryzacji. Model ten jest taką właśnie
standaryzacją. Celem jego stosowania jest umożliwienie wykorzystania
dobrodziejstw przetwarzania rozproszonego w środowisku heterogenicznych zasobów
i domen [1]. Inernet charakteryzuje się właśnie taką heterogenicznością
swych zasobów. W modelu tym systemy rozproszone charakteryzują się:

  • rozproszeniem składników,
  • współbieżnością, oznaczającą, że pewne składniki mogą działać równolegle z innymi,
  • brakiem globalnego stanu,
  • częściowymi uszkodzeniami – składnik systemu może przestać funkcjonować niezależnie od innych (system scentralizowany działa lub nie),
  • asynchronicznością – działania nie są taktowane przez jeden globalny zegar. Nie można zakładać, że zmiany dokonane w systemie zachodzą w jednej chwili.

Systemy rozproszone cechują się ponadto:

  • Heterogenicznością – w skład systemu wchodzą składniki zbudowane w oparciu o różne technologie dotyczące sprzętu, systemów operacyjnych, oprogramowania, komunikacji, protokołów itp.
  • Autonomią – (często) nie ma jednej organizacji nadzorującej.
  • Ewolucją – system jest zmieniany zgodnie z postępem technicznym, wymaganiami itp.
  • Mobilnością – dane, zasoby, użytkownicy mogą zmieniać swe fizyczne położenie.

W modelu ODP kluczowa jest specyfikacja usługi; poprzez
grupowanie tych usług, ich właściwości i ich uzgadnianie, osiąga się możliwość
strukturyzacji systemów heterogenicznych. Model RM-ODP definiuje:

  • podział specyfikacji systemu na widoki (ang. viewpoints) w celu uproszczenia opisu złożonych systemów,
  • zbiór ogólnych koncepcji dla wyrażania specyfikacji tych widoków,
  • zasady oceny przystosowania dla systemów ODP,

  • model wspierający infrastrukturę.

Widoki określają różne aspekty systemu:

  • biznesowy – określa misję systemu,
  • informacyjny – określa jakie informacje mają być przechowywane i przetwarzane,
  • operacyjny (obliczeniowy ang. computing) – który opisuje system jako zbiór obiektów, wchodzących w interakcje przez interfejsy,
  • inżynierski – skupiający się na mechanizmach zapewniających rozproszenie,
  • technologiczny – skupiający się na szczegółach komponentów składających się na system.

Taki podział ma (w pewnym stopniu) odzwierciedlenie w
procesie projektowania systemów informatycznych i dlatego jest on istotny przy
rozważaniu problemów związanych z projektowaniem aplikacji internetowych. (W
UML model biznesowy to procesy biznesowe i przypadki użycia).

Istotną cechą jest przezroczystość rozproszenia.
Projektanci nie powinni być zmuszeni do uświadamiania sobie mechanizmów związanych
z rozproszeniem. Podstawowym pojęciem koncepcyjnym w RM-ODP jest obiekt i inne
pojęcia z nim związane. System może być opisany jako kolekcja powiązanych,
wchodzących w interakcje obiektów. Obiekty mogą mięć różną ziarnistość
(liczba na ekranie monitora lub cała organizacja), mogą przejawiać różne
zachowanie i mieć wbudowaną równoległość. Interakcja może być
synchroniczna lub asynchroniczna. Obiekty są encjami zawierającymi dane i
oferującymi usługi. Obiekty charakteryzuje:

  • Hermetyzacja (enkapsulacja) polegająca na tym, że dostęp do informacji zawartych w obiekcie może być realizowany przy pomocy interakcji dostępnych dzięki interfejsowi obiektu. Szczegóły wewnętrzne są ukryte. Ponieważ obiekty są „hermetyczne” interakcja z obiektem nie może wywoływać efektów ubocznych w postaci zmiany stanu innych obiektów, bez interakcji z tymi obiektami. Zmiana stanu obiektu może być wynikiem tylko akcji wewnętrznych lub interakcji z otoczeniem obiektu.
  • Abstrakcja – Obiekty oferują usługi; opis usługi abstrahuje od jej realizacji. Ten sam obiekt może być implementowany na różne sposoby w różnych systemach, ale każda implementacja dostarcza tej samej usługi. Usługi mogą być implementowane w różnych technologiach.
  • Zachowanie – stan obiektu definiowany jest przez zbiór potencjalnych akcji, w których obiekt może brać udział. Zachowanie i stan są zatem powiązane. Obiekt jest zachowawczo zgodny z innym jeśli zamiana tych obiektów nie może być wykryta przez otoczenie.
  • Interfejsy – obiekty mogą wchodzić w interakcje tylko przy pomocy interfejsów. Obiekt może mieć wiele interfejsów.

Obiekty opisują szablony (ang. template – nie ma nic wspólnego
ze wzorcami znanymi z C++), a nie klasy jak w popularnych językach
programowania (np. Java lub C++). Obiekty o takim samym zachowaniu opisywane mogą
być przy pomocy tego samego szablonu. Jest to istotne rozróżnienie, ponieważ
klasy w językach programowania istnieją na poziomie kodu źródłowego. Pojęcie
szablonu nie jest ograniczone do języka programowania. Drugą istotą różnicą
jest to, że obiekty danej klasy na poziomie języka programowania mają taką
samą „budowę wewnętrzną” obejmującą dane, realizację algorytmów
itp. Zgodność obiektu z szablonem abstrahuje od „budowy wewnętrznej”
obiektu. Wystarczy, że dwa obiekty zachowują się tak samo, aby były zgodne z
tym samym szablonem. Realizacja usług może być zupełnie różna. Obiekty mogą
być realizowane w różnych technologiach. W modelu RM-ODP pojęcie typu różni
się od pojęcia analogicznego znanego z języków programowania. W języku
programowania C zapis int a; oznacza, że a jest liczbą całkowitą.
W modelu RM-ODP typ jest własnością grupy obiektów. Predykat jest żółty
jest typem. Typy niejawnie dokonują podziału obiektów na klasy (pojęcie
klasy odpowiada tu klasie abstrakcji z logiki). Klasa jest kolekcją obiektów
skojarzonych z danym typem. Pojęcie klasy odpowiada więc zbiorowi obiektów
mających pewną własność. Hierarchia klasa-podklasa odpowiada hierarchii zbiór-podzbiór.
Z każdym typem (czyli właściwością) skojarzona jest klasa (czyli zbiór, który
być może pusty). Ważne jest to, że klasie z języków programowania
odpowiada szablon w modelu RM-ODP, z tym, że abstrahuje on od technologii
implementacji i samej implementacji. Bardziej od samych nazw istotne jest zupełne
pominięcie implementacji na korzyść obserwowanej z zewnątrz funkcjonalności.

Komunikacja między procesami i protokoły komunikacyjne jako podstawa
funkcjonowania aplikacji interetowych

Pomimo tego, że najlepiej byłoby – co już
powiedziano – abstrahować od szczegółów technicznych związanych z
komunikacją, należy zdawać sobie sprawę jak owa komunikacja przebiega.
Sensownym punktem wyjścia do dalszych rozważań jest przyjrzenie się
komunikacji między procesami. Do komunikacji stosujemy m.in.:

  • semafory,
  • pamięć dzieloną,
  • łącza komunikacyjne,
  • kolejki FIFO,
  • gniazda,
  • zdalne wywołanie procedury.


Semafory
służą do synchronizacji procesów np. przy
dostępie do dzielonych zasobów. Nie umożliwiają one wymiany dużej ilości
danych. Istota komunikacji poprzez pamięć dzieloną polega na tym, że
procesy używają wspólnego fragmentu obszaru przestrzeni adresowej.


Łącza komunikacyjne
umożliwiają przepływ
danych w jednym kierunku pomiędzy procesami.


Kolejki Fifo
różnią się tym od łączy
komunikacyjnych, że identyfikowane są przez nazwę. Umożliwia to komunikację
procesów nie spokrewnionych, tzn. takich gdzie jeden nie jest przodkiem
drugiego. Powyższe metody komunikacji stosuje się do komunikacji procesów w
jednym systemie. Nie mają więc one zastosowania przy komunikacji procesów
działających w różnych przestrzeniach adresowych.


Gniazda
mogą być używane do komunikacji między
procesami zarówno w jednym (protokoły należące do dziedziny Unixa)
jak i pomiędzy różnymi systemami. Gniazda są pewnym mechanizmem na poziomie
programowania, nie są rozwiązaniem na poziomie sprzętu. Pozwalają na
korzystanie z różnych protokołów komunikacyjnych. Pod Unixem
popularne są interfejsy:

  • interfejs gniazd BSD,
  • interfejs warstwy TLI,

umożliwiające wykorzystanie gniazd w programach użytkowania.
Gniazda w systemie Windows bazują na gniazdach BSD. Ten ostatni stał się
zresztą standardem. Ideą gniazd jest umożliwienie abstrahowania od szczegółów
związanych z protokołami komunikacyjnymi. Gniazda umożliwiają użycie różnych
protokołów komunikacyjnych np.

  • tcp/ip,
  • udp/ip,
  • xns (systemy sieciowe Xerox),
  • protokoły z dziedziny unixa.

Tworząc (programowo) gniazdo, a mówiąc ściśle jego
deskryptor należy dostarczyć pewnych informacji. Korzystając z gniazd BSD
należy określić protokół oraz dane związane z asocjacją (między
systemami) takie jak adres lokalny, adres zdalny, proces lokalny,
proces zdalny.
Konkretne postępowanie zależy od tego jakiego protokołu się
używa. Idea polega na określeniu kto z kim (adres) i jak (protokół) się
komunikuje. W praktyce dla protokołów z dziedziny internetu tworząc gniazdo
określa się: protokół (tcp, udp), internetowy adres maszyny zdalnej (32
bity) i numer portu maszyny zdalnej. Transmisja może być połączeniowa lub
bezpołączeniowa – zależy to od protokołu. Przy transmisji połączeniowej
należy przed przesłaniem danych nawiązać połączenie z systemem zdalnym.
Transmisja może być strumieniowa lub datagramowa.

Na poziomie komunikacyjnym maszyny oferują swoje usługi za
pomocą portów co pokazuje rysunek 1 (elipsy oznaczają procesy, prostokąty
narysowane linią przerywaną systemy, nie wypełnione prostokąty narysowane
linią ciągłą oznaczają porty, wypełnione prostokąty oznaczają gniazda).
Porty identyfikowane są przez unikatowe w systemie 16 bitowe liczby, gniazda zaś
umożliwiają dostęp do portów. Tworząc gniazdo określa się numer portu.
Gniazdo identyfikowane jest przez deskryptor gniazda. Jest to niewielka liczba
całkowita (zależna od konfiguracji systemu, ale zazwyczaj mniejsza niż 64)
podobna do deskryptora uzyskiwanego przy otwarciu pliku (identyfikowanego przez
ścieżkę i nazwę).

Komunikacja między systemami na poziomie portów
Rysunek 1. Komunikacja między systemami na poziomie portów

Standardowe usługi takie jak telnet lub ftp
mają przyporządkowane ogólnie znane numery portów. Usługa zdalnego
transferu plików (FTP) ma standardowo przypisany port o numerze 21. W
systemie istnieje wiele portów, każdy jest identyfikowany przez unikalną 16
bitową liczbę. Gniazda umożliwiają dostęp do portów. Przyporządkowanie usług
do portów określa w systemach Unix i Windows plik services. W
systemie WINDOWS znajduje się on w katalogu WINDOWS, w systemie UNIX w /etc/services.
Poniżej znajduje się jego fragment (w formacie: nazwa_usługi nr_portu/ protokół
alias #komentarz):


ftp 21/tcp

telnet 23/tcp

smtp 25/tcp mail

time 37/udp timserver

printer 515/tcp spooler # line printer spooler

portmap 111/tcp

Gniazda mogą być mechanizmem używanym do tworzenia
aplikacji rozproszonych jak również mogą stanowić fundament do budowy
bardziej zaawansowanych mechanizmów komunikacyjnych.


Zdalne wywołanie procedury (RPC)
– popularną jego
specyfikacją jest SUN RPC firmy SUN. W tradycyjnym programowaniu
(strukturalnym) złożone zadanie dekomponuje się na zadania prostsze.
Odpowiednikiem takich prostszych zadań są procedury i funkcje.

W języku C wykonanie programu polega na wykonaniu
funkcji main. Funkcje wywoływane przez proces istnieją w obrębie tego
procesu lub są funkcjami systemowymi istniejącymi w obrębie jądra systemu
operacyjnego. Zdalne wywołanie procedury jest mechanizmem umożliwiającym wywołanie
procedury istniejącej w ramach innego procesu, który znajduje się w ogólności
na innej maszynie. Procedura zdalna (SUN RPC) identyfikowana jest przez:

  • adres maszyny,
  • identyfikator programu (32 bitowa liczba),
  • identyfikator procedury (32 bitowa liczba),
  • identyfikator wersji programu.

Procedura istnieje więc w ramach programu zdalnego, na który
składać może się składać kilka procedur zdalnych. Każdy program zdalny ma
unikalny identyfikator. Usługa portmap, mająca przyporządkowany port
111, dokonuje odwzorowania 32 bitowego numeru programu RPC na 16 bitowy
numer portu, przez który następować będzie komunikacja. Działanie tej usługi
jest warunkiem niezbędnym dla działania RPC. Format komunikatów określany
jest przez specyfikację XDR. Specyfikacja ta określa m.in. czy
komunikat jest wywołaniem procedury czy odpowiedzią, zawiera identyfikator
komunikatu potrzebny dla dopasowania odpowiedzi do komunikatu, numer programu,
numer procedury itp. Specyfikacja RPC określa też sposób pakowania, tłumaczenia
(np. całkowitoliczbowy typ danych integer może mieć różną
reprezentację, w zależności od architektury komputera) i przesyłania danych.
Uproszczony schemat wywołania procedury zdalnej znajduje się na rysunku 2.

Mechanizm działania RPC
Rysunek 2. Mechanizm działania RPC

Trzeba pamiętać, że przed wywołaniem procedury następuje
odpytanie maszyny, na której znajduje się serwer (przy pomocy usługi portmap
– port 111) o numer portu przyporządkowany programowi RPC. Troszczą
się o to same procedury RPC, a nie programista. Należy jednak mieć świadomość,
że w RPC komunikacja odbywa się poprzez porty przy pomocy gniazd. RPC używa
protokołu TCP lub UDP. Do generowania stopek klienta i serwera używa się
programu rpcgen, który generuje je na postawie specyfikacji. Specyfikację
tę tworzy się w języku podobnym do C. Poniżej znajduje się przykładowa
specyfikacja programu RPC o identyfikatorze 0x21234432, wersji 1.
Program ten zawiera procedurę pow o identyfikatorze 1.

program DO_KWADRATU{
version DO_KWADRATU_VERSION{
long pow(long)=1;
}=1;
}=0x21234432;

Podsumowując można powiedzieć, że w systemach
rozproszonych, spośród omówionych powyżej mechanizmów używa się gniazd i
zdalnego wywołania procedury. Gniazda dostarczają mechanizmów do przesyłania
danych, a RPC zapewnia rozproszenie aplikacji na poziomie programowania
strukturalnego. Są to bardzo mocne mechanizmy programistyczne. Ich użycie
sprawia, że projektowanie oprogramowania jest zorientowane na komunikację.
Mechanizmy te stanowią podstawę innych, bardziej zaawansowanych rozwiązań, w
których projektowanie i programowanie zorientowane jest na aplikację, a
rozproszenie aplikacji odbywa się na poziomie obiektów. W przypadku gniazd
trudno jest nawet rozważać zgodność z modelem obiektowym ze względu na zupełnie
inny poziom mechanizmu – gniazda są mechanizmem przesyłania danych i nie
oferują usług. Jeśli chodzi o RPC to pozwala ono łączyć różne systemy
(np. Unix i Windows) i pozwala na zdefiniowanie interfejsu niezależnego od
implementacji. Jakkolwiek na poziomie implementacji jest ono strukturalne, a nie
obiektowe. Oba mogłyby być zakwalifikowane do widoku inżynierskiego lub
technologicznego (z RM-ODP). Powyżej opisane zostały mechanizmy komunikacyjne,
dające dostęp do zasobów wykorzystywanych przy komunikacji. To, jak przebiega
sama komunikacja określają protokoły. Można powiedzieć, że protokół jest
formalnym opisem formatu komunikatów i zasad ich wymiany. Protokoły sieciowe
występują na różnych poziomach komunikacji. Formalnie komunikację w
sieciach komputerowych opisują pewne modele (np. ISO/OSI). Są one złożone z
pewnej ilości warstw (ISO/OSI z 7). Dana warstwa (np. transportowa w ISO/OSI) w
systemie lokalnym komunikuje się z tą samą warstwą w systemie zdalnym (dane
w rzeczywistości są przekazywane do warstwy niższej lub wyższej, a
rzeczywista komunikacja pomiędzy maszynami przebiega w warstwie najniższej).
Zasady komunikacji w danej warstwie opisują protokoły komunikacji tej warstwy.
Dokładne przedstawienie modelu komunikacji przynależy bardziej do sieci i
dlatego będzie tu pominięte. Z punktu widzenia tworzenia aplikacji
rozproszonych istotne są protokoły warstwy sieciowej, transportowej, a przede
wszystkim warstwy zastosowań.

W tabeli 1 znajduje się krótki opis protokołów związanych
z internetem należących do warstwy sieciowej (za [1]).

Tabela 1. Przegląd protokołów komunikacyjnych warstwy
sieciowej związanych z internetem

nazwa protokołu opis
Protokół między sieciowy (IP) Jest to protokół bezpołączeniowy obsługujący
dostarczanie pakietów w sieciach. Protokół ten jest protokołem
zawodnym. Bezpośrednio nie korzysta się z tego protokołu.
Protokół między sieciowych komunikatów sterujących (ICMP) Służy do przesyłania informacji sterujących i o błędach.
Popularny program ping używa bezpośrednio tego protokołu.
Protokół odwzorowywania adresów (ARP) Odwzorowuje adresy internetowe (32 bitowe) na adresy sprzętowe
(48 bitowe numery kart sieciowych).
RARP Odwzorowuje adresy sprzętowe na adresy internetowe.

Z użyciem tych protokołów zbudowane zostały protokoły
warstwy transportowej, na poziomie której współpracują ze sobą procesy.
Protokoły warstwy transportowej zostały opisane w tabeli 2.

Tabela 2. Protokoły warstwy transportowej

nazwa protokołu opis
Protokół sterowania transmisją (TCP) Jest to protokół połączeniowy. Umożliwia on niezawodne, dwukierunkowe przesyłanie danych.
Protokół datagramów użytkownika (UDP) Jest protokołem bezpołączeniowym, zawodnym, obsługującym przesyłanie datagramów.

Szczegóły dotyczące protokołów można znaleźć w ich
specyfikacjach, mogą być one użyteczne dla osób tworzących np. aplikacje
monitorujące ruch w sieci lub inne oprogramowanie sieciowe. Przy pomocy
wymienionych protokołów warstwy transportowej zaimplementowano, protokoły
tekstowe (ang. ASCII Request/ Replay protocols) należące do warstwy zastosowań.
Są one bardzo istotne z punktu widzenia wytwarzania aplikacji internetowych.
Osoby, które chciałyby stworzyć własny program pocztowy (klient poczty), własną
przeglądarkę lub np. zintegrowany program do obsługi biura, muszą zapoznać
się ze specyfikacjami tych protokołów. Także współpraca serwera webowego z
programami działającymi po jego stronie jest pochodną protokołów z tej
grupy (w praktyce HTTP). Ich opis znajduje się w tabeli 3.

Tabela 3. Przykładowe protokoły tekstowe

nazwa protokołu opis
HTTP Protokół działający na poziomie aplikacji dla rozproszonych, współpracujących systemów informatycznych. Używa zazwyczaj
TCP/IP. Może jednak używać innych protokołów, które dają możliwość mapowania struktur żądania (ang.
request) i odpowiedzi (ang. response) na struktury danych. Serwery webowe nasłuchują na porcie 80.
FTP Protokół przesyłania plików. Zaimplementowany z użyciem
TCP. Używa osobnych połączeń dla komend i wymiany danych. DTP (Data Transfer
Process) odpowiada za wymianę danych. Interpreter protokołu PI implementuje protokół
FTP. Serwer FTP nasłuchuje na porcie 21. Połączenia związane z wymianą danych inicjuje serwer z portu 20 do portu podanego przez klienta w komendzie PORT.
SMTP Protokół (prostego) przesyłania poczty. Zaimplementowany z użyciem
TCP. Program pocztowy nasłuchuje na porcie 25.
POP Protokół służący do odbierania poczty ze skrzynki pocztowej. Zapewnia autoryzację. W użyciu wersja trzecia tego protokołu tzw. POP3.
IMAP Protokół umożliwiający dostęp do poczty z serwera pocztowego, bez ściągania plików. Użyteczny dla użytkowników często zmieniających komputery na których pracują, chcących mieć dostęp do swojej poczty z różnych komputerów.
NNTP Protokół służy do wymiany informacji USENET’a w
internecie.

Przykład (nieco zmodyfikowany w stosunku do [6]) wysłania
emaila przy pomocy protokołu SMTP o treści ala ma kota przez
Smith’a do Jones’a (s – wysłane, r – odebrane):

R: 220 BBN-UNIX.ARPA Simple Mail Transfer Service Ready
S: HELO USC-ISIF.ARPA
R: 250 BBN-UNIX.ARPA
S: MAIL FROM:<Smith@USC-ISIF.ARPA>
R: 250 OK
S: RCPT TO:<Jones@BBN-UNIX.ARPA>
R: 250 OK
S: DATA
R: 354 Start mail input; end with <CRLF>.<CRLF>
S: ala ma kota
S: .
R: 250 OK
S: QUIT
R: 221 BBN-UNIX.ARPA Service closing transmission channel


Serwer webowy i jego współpraca z przeglądarką

Najprostsza aplikacja internetowa kojarzy się powszechnie z
aplikacją używającą przeglądarki internetowej. Wpisanie do przeglądarki
adresu:

http://www.gruszka.comindex.htm

spowoduje ściągnięcie pliku index.htm znajdującego
się lokalnie na komputerze www.gruszka.com. Plik ten może lokalnie
znajdować się w katalogu c:interpubwwwroot .

Przeglądarka zinterpretuje ten plik, czego skutkiem będzie
wyświetlenie strony w przeglądarce. W powyższym adresie są następujące składniki:

  • www – nazwa komputera (ang. host name),
  • gruszka – nazwa domeny (ang. domain name),
  • com – nazwa strefy (ang. top level domain name)
  • http – (poprzedza adres) określa protokół

Przeglądarka komunikując się z serwerem webowym, używa
protokołu HTTP (ang. hyper text transfer protocol).

W rzeczywistości ściągnięcie nawet najprostszej
statycznej strony jest bardziej skomplikowane. Adres tekstowy wpisany przez człowieka
musi być zamieniany na adres IP w postaci:

127.100.1.1

adres taki jest 32 bitową liczbą i dla wygody zapisywany
jest w tzw. notacji kropkowej.

W początkowym stadium rozwoju internetu korzystało się wyłącznie
z adresu IP. Nieco później w lokalnie przechowywanym pliku (hosts) zapisywano
odwzorowania adresów tekstowych na adresy IP. W roku 1983 opracowano DNS,
który jest rozproszoną usługą katologu. Usługa katalogu DNS składa
się z:

  • danych DNS,
  • serwerów DNS,
  • protokołów służących do pobierania danych z serwerów.

DNS może być rozumiane jako rozproszona baza danych. Nazwy
domen są utrzymywane przez firmę Network Solutions.

Po wpisaniu do przeglądarki nazwy tekstowej łączy się ona
z działającym „w pobliżu” (podanym przy konfiguracji sieci)
serwerem DNS, przesyłając adres tekstowy. Serwer DNS zwraca adres IP. Po
otrzymaniu adresu IP serwera przeglądarka może dokonać połączenia z właściwym
serwerem. Serwer webowy nasłuchuje zazwyczaj na porcie 80. Z takim portem łączy
się domyślnie przeglądarka, jakkolwiek po dwukropku w adresie można podać
inny port.


Serwer webowy
jest programem, działającym na serwerze,
który nasłuchuje nadchodzących żądań a następnie je obsługuje. Obsługa
ta może polegać np. na odnalezieniu i odesłaniu pliku lub uruchomieniu
jakiegoś programu. Tak czy owak wykonanie żądania wiąże się ze zwróceniem
jakiś danych do przeglądarki. Żądania kierowane do serwera webowego zawierają
nazwę pliku, skryptu, programu itp. oraz ewentualne dane wprowadzone przez użytkownika.
Żądania używają następujących metod (żądania i odpowiedzi, metody itp.
opisuje dokładnie specyfikacja protokołu HTTP):

  • HEAD – pobranie informacji o dokumencie,
  • GET – metoda ta używana jest do wykonania żądania.
    Jego parametry występują po łańcuchu opisującym lokację (adres) i są
    od niego oddzielone znakiem ?. Parametry są zapisywane jako pary klucz=wartość;
    separatorem jest &. Jest to metoda domyślna dla wszystkich żądań.
    Wyświetlane dane mogą być nieaktualne, gdyż sprawdzana jest najpierw
    pamięć podręczna przeglądarki. Ilość przekazywanych do serwera danych
    jest ograniczona.
  • POST – metoda ta pobiera dane z serwera. Pozwala
    jednak na przekazanie większej ilości parametrów. Żądanie jest zawsze
    przesyłane do serwera z pominięciem przeszukiwania pamięci podręcznej.
    Powinna ona być używana wtedy, kiedy zapytanie mogło zmienić dane
    przechowywane przez serwer.

Istnieją jeszcze metody: PUT, DELETE, TRACE, CONNECT ale są
one rzadziej używane.

Funkcja serwera webowego polega na przekazaniu żądania do
specjalnego skryptu, programu lub na pobraniu pliku. Jeżeli jest to konieczne,
zostaje załadowane odpowiednie środowisko potrzebne do wykonania tego skryptu.
Serwer webowy odpowiada zatem za przekierowanie żądań, tam gdzie będą obsłużone,
a następnie przekazaniu odpowiedzi wygenerowanej w miejscu obsłużenia z
powrotem do przeglądarki. Biorąc za punkt odniesienia komunikację przy pomocy
gniazd, serwer webowy dostarcza mechanizmów do zdalnego wykonywania programów
i pobierania zdalnych plików, ukrywając techniczne szczegóły komunikacji
sieciowej. Serwer webowy może być rozumiany jako mechanizm pozwalający na
korzystanie z protokołu HTTP, tak jak gniazda pozwalają korzystać z protokołów
warstwy transportowej (TCP, UDP). (Przeglądarka z punktu widzenia użytkownika
takim interfesem nie jest, z punktu widzenia programisty jest.) Popularnym (i
najprostszym) interfejsem pozwalającym na komunikację pomiędzy serwerem a
programami wykonywanymi po stronie serwera jest CGI (ang. common gateway
interface), jakkolwiek istnieją bardziej zawansowane rozwiązania.

Prosty przykład komunikacji pomiędzy przeglądarką a
serwerem webowym znajduje się na rysunku 3. Prostokąty narysowane linią
przerywaną odpowiadają „gotowym” rozwiązaniom (np. dostarczanym
wraz z systemem). Prostokąty narysowane linią ciągłą odpowiadają składnikom,
które są projektowane i programowane w procesie wytwarzania aplikacji
internetowej użytkownika.

Prosty przypadek współpracy przeglądarka - serwer webowy
Rysunek 3. Prosty przypadek współpracy przeglądarka – serwer webowy

Według [3] (stan na maj 2001) najczęściej używanymi
serwerami webowymi są:

  • Apache
  • Microsoft-IIS
  • Netscape-Enterprise
  • Zeus

Prosta aplikacja z przeglądarką internetową po stronie
klienta i skryptami CGI po stronie serwera, może być punktem odniesienia do różnych
typów aplikacji internetowych. (Tak jak RM-ODP jest punktem odniesienia przy
porównywaniu różnych rozwiązań technologicznych.)


Skrypty CGI

CGI jest specyfikacją interfejsu pomiędzy serwerem webowym
a programami użytkownika. Programy te nazywa się skryptami CGI. W odróżnieniu
do zwykłych statycznych stron HTML, które istnieją po stronie serwera w
niezmiennej postaci, skrypty są wykonywane w czasie rzeczywistym. Dlatego mogą
one dostarczać dynamicznych informacji. W tym sensie para przeglądarka-serwer
dostarcza po prostu mechanizmów do uruchamiania programów w systemie zdalnym;
protokół HTTP definiuje sposób komunikacji (przeadresowanie) wejścia/wyjścia
tych programów. Nie ma więc mowy na tym poziome o rozproszeniu obiektów. Z
serwera do przeglądarki mogą być przesyłane różne pliki np. binarne pliki
odpowiadające obiektom (o rodzaju pliku jaki będzie przesyłany przeglądarka
jest informowana przy pomocy tzw. pliku MIME). Cały program wykonywany jest
zdalnie korzystając ze zdalnych zasobów. Przypomnieć należy że skrypty CGI
można pisać praktycznie w każdym języku programowania np.

  • C/C++,
  • Perl,
  • skrypty powłoki Unixa,
  • Visual Basic,
  • ASP,
  • JSP.

Programy napisane w C lub C++ muszą być skompilowane do
postaci wykonywalnej. Skrypty napisane w językach takich jak Perl, skrypty powłoki
Unix są interpretowane w czasie wykonania. Wybór konkretnego języka jest
bardziej kwestią upodobań, gustu i wygody. (Programowanie w językach C,C++
sprawia niektórym pewne trudności.)
Mówiąc o tym, że skrypty CGI są wykonywane na bieżąco po stronie serwera
należy być świadomym, że wykonanie takiego skryptu (lub skompilowanego
programu) wiąże się z utworzeniem przez system operacyjny procesu „w
ramach” którego będzie ten program wykonany. Dlatego skrypty CGI nie
zapewniają skalowalności rozwiązań. Przy dużej liczbie odwołań do serwera
może nastąpić jego zawieszenie. Działanie skryptu CGI przedstawia rysunek 4.
Grube strzałki oznaczają komunikację na poziome protokołu HTTP. Strzałki
narysowane cienką linią ciągłą opowiadają komunikacji pomiędzy serwerem a
procesami użytkownika, poprzez CGI. Strzałki przerywane odpowiadają relacji:
skrypt CGI jako zasób i jako proces w trakcie wykonania. Jest to ważne ponieważ
skrypt CGI jest identyfikowany jako plik w określonym (najczęściej cgi-bin/)
katalogu. Strzałki narysowane linią dwu kropkowaną odpowiadają komunikacji
pomiędzy procesem (skryptem w trakcie wykonania) a zasobem np. bazą danych.

Komunikacja poprzez CGI
Rysunek 4. Komunikacja poprzez CGI

Załóżmy, że użytkownik wpisał do przeglądarki 2 następujący
URL:

www.gruszka.com/cgi-bin/ola.exe?p1=aa&p2=ab

(określenie protokołu przed adresem pominięto).

Niech przeglądarka użyje metody GET. Po nawiązaniu
połączenia (samo nawiązanie połączenia odbywa się na poziomie protokołu
TCP, a nie HTTP) przeglądarka prześle następujące żądanie (protokół HTTP)
do serwera webowego:

GET http://www.gruszka.com/cgi-bin/ola.exe?p1=aa&p2=ab
HTTP/1.1

Serwer webowy odnajdzie plik ola.exe i wykona go
przekazując parametry p1=aa oraz p2=ab

zgodnie ze specyfikacją CGI. Sposób przekazywania parametrów
wywołania do skryptu CGI zależy do metody określonej w zmiennej środowiskowej
REQUEST_STRING:

  • GET – przy użyciu tej metody parametry są przekazywane w zmiennej środowiskowej QUERY_STRING,
  • POST – dane są przekazywane do standardowego strumienia wejściowego (stdin w języku C), mogą być opcjonalnie przekazywane też w QUERY_STRING. Ilość (w bajtach) danych do odczytania określona jest w zmiennej CONTENT_LENGTH.

Standardowe wyjście skryptu (w C stdout) jest przez
serwer „przechwytywane” i na jego podstawie tworzy się odpowiedź,
którą serwer wyśle przeglądarce.

Niniejszy bardzo prosty program (w terminologii CGI skrypt)
napisany w języku C:

(wykonanie programu w C rozpoczyna się od wywołania funkcji
main(), funkcja printf() powoduje wysłanie do wyjścia łańcucha
znaków, getenv() pobiera zmienną środowiskową)

#include <stdio.h>
#include <stdlib.h>

main(int argc, char* argv[])
{
printf("Content-type: text/htmlnn");
printf("<html>n");
printf("<head>n");
printf("<title>Witam</title>n");
printf("</head>n");
printf("<body>n");
printf("<center>n");
printf("<h1>wprowadzone parametry: %s</h1>n",getenv("QUERY_STRING"));
printf("<h1>adres hosta wysyłającego zapytanie:
%s</h1>n", getenv("REMOTE_ADDR"));
printf("<h1>metoda: %s</h1>n",
getenv("REQUEST_METHOD"));
printf("<h1>port: %s</h1>n", getenv("SERVER_PORT"));
printf("<h1>protokół serwera: %s</h1>n",
getenv("SERVER_PROTOCOL"));
printf("<h1>serwer: %s</h1>n",
getenv("SERVER_SOFTWARE"));
printf("<h1>numer wersji CGI: %s</h1>n",
getenv("GATEWAY_INTERFACE"));
printf("</center>n");
printf("</body>n");
printf("</html>n");
return(0);
}

Pobiera (po skompilowaniu oczywiście) ze zmiennych środowiska
pewne informacje i odsyła je do przeglądarki:

  • wprowadzone parametry: p1=aa&p2=ab
  • adres hosta wysyłającego zapytanie: 127.0.0.1
  • metoda: GET
  • port: 80
  • protokół serwera: HTTP/1.1
  • serwer: Microsoft-IIS/4.0
  • numer wersji CGI: CGI/1.1

Do jego napisania wystarcza znajomość języka C oraz
podstawowa znajomość interfejsu CGI i języka HTML. Program ten (skrypt) nie różni
się w zasadzie od prostego programu napisanego w języku C, który działa w
trybie tekstowym. Pobieranie zmiennych środowiskowych stosuje się np. do
odczytania zmiennej systemowej PATH. Tak więc pobieranie zmiennych środowiskowych
nie jest samo w sobie charakterystyczne dla programowania skryptów CGI.
Charakterystyczne są nazwy tych zmiennych i elementy języka HTML związane z
formatowaniem.

c.d.n.

Literatura
[1] Reference Model of Open Distributed Processing
[2] W. Richard Stevens, Programowanie zastosowań sieciowych w systemie Unix
WNT 1998
[3] Netcraft Web Server Survey http://www.netcraft.com/survey/
[4] Professional Java Server Programing WROX Ltd.1999
[5] E. Ladd, J, O’Donnel Javascript, CGI, VBScript Lynx-SFT
[6] An Internet Encyclopedia http://www.freesoft.org/CIE/index.htm