2. Podstawy
W niniejszym rozdziale przedstawiamy podstawy programowania internetowego. Jego głównym celem jest zapoznanie czytelnika z głównymi zasadami programowania internetowego przed zastosowaniem ich w praktyce przy użyciu konkretnego języka i środowiska. Zawiera on liczne przykłady, które warto przetestować, aby stopniowo „wczuć się” w filozofię tworzenia aplikacji internetowych.
2.1. Elementy składowe aplikacji internetowej
![]() |
Numer | Rola | Typowe przykłady |
OS Serwer | Linux, Windows | |
Serwer WWW | Apache (Linux, Windows) IIS (NT), PWS (Win9x) | |
Skrypty wykonywane po stronie serwera. Mogą być uruchamiane przez moduły serwera lub przez programy zewnętrzne względem serwera (CGI). | PERL (Apache, IIS, PWS) VBSCRIPT (IIS, PWS) JAVASCRIPT (IIS, PWS) PHP (Apache, IIS, PWS) JAVA (Apache, IIS, PWS) C#, VB.NET (IIS) | |
Baza danych – może znajdować się na tym samym komputerze co program, który z niej korzysta, lub na innym komputerze za pośrednictwem Internetu. | Oracle (Linux, Windows) MySQL (Linux, Windows) Access (Windows) SQL Server (Windows) | |
OS Klient | Linux, Windows | |
Przeglądarka internetowa | Netscape, Internet Explorer | |
Skrypty uruchamiane po stronie klienta w przeglądarce. Skrypty te nie mają dostępu do dysków komputera klienckiego. | VBscript (IE) JavaScript (IE, Netscape) PerlScript (IE) Aplety JAVA |
2.2. Wymiana danych w aplikacji internetowej z formularzem
![]() |
Numer | Rola |
Przeglądarka po raz pierwszy żąda kodu URL dla kodu (http://machine/url). Nie przekazano żadnych parametrów. | |
Serwer WWW wysyła mu stronę internetową o tym URL. Może to być strona statyczna lub wygenerowana dynamicznie przez skrypt serwera (SA), który mógł wykorzystać zawartość baz danych (SB, SC). W tym przypadku skrypt wykryje, że żądano pliku URL bez przekazania parametrów, i wygeneruje początkową stronę WEB. Przeglądarka odbiera stronę i wyświetla ją (CA). Skrypty po stronie przeglądarki (CB) mogły zmodyfikować stronę początkową wysłaną przez serwer. Następnie, w wyniku interakcji między użytkownikiem (CD) a skryptami (CB), strona internetowa zostanie zmodyfikowana. W szczególności zostaną wypełnione formularze. | |
Użytkownik zatwierdza dane z formularza, które następnie muszą zostać wysłane do serwera internetowego. Przeglądarka ponownie żąda pierwotnego skryptu URL lub innego, w zależności od sytuacji, i jednocześnie przekazuje serwerowi wartości z formularza. W tym celu może wykorzystać dwie metody o nazwach GET i POST. Po otrzymaniu żądania od klienta serwer uruchamia skrypt (SA) powiązany z żądanym URL, który wykrywa parametry i przetwarza je. | |
Serwer dostarcza stronę WEB wygenerowaną programowo (SA, SB, SC). Ten etap jest identyczny z poprzednim etapem 2. Wymiana danych odbywa się teraz zgodnie z etapami 2 i 3. |
2.3. Kilka zasobów
Poniżej znajduje się lista zasobów umożliwiających instalację i korzystanie z niektórych narzędzi do tworzenia stron internetowych. W załączniku znajduje się instrukcja instalacji tych narzędzi.
- Apache, instalacja i wdrożenie, O'Reilly | |
- Programowanie w języku Perl, Larry Wall, O'Reilly - Aplikacje w języku Perl: CGI, Neuss i Vromans, O'Reilly - Dokumentacja HTML dołączona do pakietu Active Perl | |
- Programowanie stron internetowych z wykorzystaniem PHP, Lacroix, Eyrolles - Podręcznik użytkownika PHP dostępny na stronie internetowej PHP | |
- Interfejs między WEB a bazą danych w WinNT, Alex Homer, Eyrolles | |
- JAVA Servlets, Jason Hunter, O'Reilly - Programowanie sieciowe w języku Java, Elliotte Rusty Harold, O'Reilly - JDBC i Java, George Reese, O'Reilly | |
- Podręcznik dotyczący MySQL jest dostępny na stronie internetowej MySQL - Oracle 8i pod systemem Linux, Gilles Briard, Eyrolles - Oracle 8i pod NT, Gilles Briard, Eyrolles |
2.4. Oznaczenia
W dalszej części będziemy zakładać, że zainstalowano pewną liczbę narzędzi i zastosujemy następujące oznaczenia:
oznaczenie | znaczenie |
katalog główny drzewa katalogów serwera Apache | |
katalog główny stron internetowych dostarczanych przez serwer Apache. To właśnie w tym katalogu głównym muszą znajdować się strony internetowe. Tak więc adres http://localhost/page1.htm odpowiada plikowi <apache-DocumentRoot>\page1.htm. | |
katalog główny drzewa katalogów powiązanego z aliasem cgi-bin, w którym można umieścić skrypty CGI dla serwera Apache. W ten sposób URL http://localhost/cgi-bin/test1.pl odpowiada plikowi <apache-cgi-bin>\test1.pl. | |
katalog główny stron internetowych generowanych przez PWS. Właśnie w tym katalogu głównym muszą znajdować się strony internetowe. Tak więc URL http://localhost/page1.htm odpowiada plikowi <pws-DocumentRoot>\page1.htm. | |
katalog główny drzewa katalogów języka Perl. Plik wykonywalny perl.exe znajduje się zazwyczaj w katalogu <perl>\bin. | |
korzeń drzewa języka PHP. Plik wykonywalny php.exe znajduje się zazwyczaj w <php>. | |
katalogu głównego drzewa katalogów Java. Pliki wykonywalne powiązane z Javą znajdują się w <java>\bin. | |
katalogu głównym serwera Tomcat. Przykłady serwletów znajdują się w katalogu <tomcat>\webapps\examples\servlets, a przykłady stron – w katalogu JSP w katalogu <tomcat>\webbapps\examples\jsp |
W przypadku każdego z tych narzędzi należy zapoznać się z załącznikiem, który zawiera instrukcje dotyczące ich instalacji.
2.5. Strony internetowe statyczne, strony internetowe dynamiczne
Strona statyczna jest reprezentowana przez plik HTML. Strona dynamiczna jest natomiast generowana „na bieżąco” przez serwer WWW. W niniejszym akapicie proponujemy różne testy z wykorzystaniem różnych serwerów WWW i różnych języków programowania, aby pokazać uniwersalność koncepcji sieci WWW.
2.5.1. Strona statyczna HTML (język znaczników HyperText)
Rozważmy następujący kod HTML:
<html>
<head>
<title>essai 1 : une page statique</title>
</head>
<body>
<center>
<h1>Une page statique...</h1>
</body>
</html>
co generuje następującą stronę internetową:
Testy

test1
- uruchom serwer Apache
- umieścić skrypt essai1.html w <apache-DocumentRoot>
- wyświetlić stronę URL http://localhost/essai1.html w przeglądarce
- zatrzymaj serwer Apache
test2
- uruchom serwer PWS
- umieścić skrypt essai1.html w pliku <pws-DocumentRoot>
- wyświetlenie strony URL http://localhost/essai1.html w przeglądarce
2.5.2. Strona ASP (Active Server Pages)
Skrypt essai2.asp:
<html>
<head>
<title>essai 1 : une page asp</title>
</head>
<body>
<center>
<h1>Une page asp générée dynamiquement par le serveur PWS</h1>
<h2>Il est <% =time %></h2>
<br>
A chaque fois que vous rafraîchissez la page, l'heure change.
</body>
</html>
generuje następującą stronę internetową:

Test
- uruchom serwer PWS
- umieść skrypt essai2.asp w <pws-DocumentRoot>
- wywołaj adres http://localhost/essai2.asp za pomocą przeglądarki
2.5.3. Skrypt PERL (Practical Extracting and Reporting Language)
Skrypt essai3.pl:
#!d:\perl\bin\perl.exe
($secondes,$minutes,$heure)=localtime(time);
print <<HTML
Content-type: text/html
<html>
<head>
<title>essai 1 : un script Perl</title>
</head>
<body>
<center>
<h1>Une page générée dynamiquement par un script Perl</h1>
<h2>Il est $heure:$minutes:$secondes</h2>
<br>
A chaque fois que vous rafraîchissez la page, l'heure change.
</body>
</html>
HTML
;
Pierwszy wiersz to ścieżka do pliku wykonywalnego perl.exe. W razie potrzeby należy ją dostosować. Po uruchomieniu przez serwer WWW skrypt generuje następującą stronę:

Test
- serwera WWW: Apache
- dla informacji, należy przejrzeć plik konfiguracyjny srm.conf lub httpd.conf, w zależności od wersji Apache'a, znajdujący się w katalogu <apache>\confs i odszukaj wiersz dotyczący cgi-bin, aby poznać katalog <apache-cgi-bin>, w którym należy umieścić plik essai3.pl.
- Umieść skrypt essai3.pl w katalogu <apache-cgi-bin>
- wywołaj adres URL http://localhost/cgi-bin/essai3.pl
Należy zauważyć, że wyświetlenie strony perl zajmuje więcej czasu niż strony asp. Wynika to z faktu, że skrypt Perl jest wykonywany przez interpreter języka Perl, który musi zostać załadowany, zanim będzie mógł wykonać skrypt. Nie pozostaje on na stałe w pamięci.
2.5.4. Skrypt PHP (Personal Home Page, procesor HyperText)
Skrypt essai4.php
<html>
<head>
<title>essai 4 : une page php</title>
</head>
<body>
<center>
<h1>Une page PHP générée dynamiquement</h1>
<h2>
<?
$maintenant=time();
echo date("j/m/y, h:i:s",$maintenant);
?>
</h2>
<br>
A chaque fois que vous rafraîchissez la page, l'heure change.
</body>
</html>
Powyższy skrypt generuje następującą stronę internetową:
Testy


-
przejrzyj plik konfiguracyjny srm.conf lub httpd.conf serwera Apache w <Apache>\confs
-
dla informacji sprawdź wiersze konfiguracyjne pliku php
test1
-
uruchom serwer Apache
-
umieścić plik essai4.php w pliku <apache-DocumentRoot>
-
wywołać plik URL http://localhost/essai4.php
test2
-
uruchom serwer PWS
-
w celach informacyjnych sprawdzić konfigurację pliku PWS pod kątem PHP
-
umieścić essai4.php w <pws-DocumentRoot>\php
-
poprosić o URL http://localhost/essai4.php
2.5.5. Skrypt JSP (Java Server Pages)
Skrypt heure.jsp
<% //program w Javie wyświetlający godzinę %>
<%@ page import="java.util.*" %>
<%
// kod JAVA do obliczania godziny
Calendar calendrier=Calendar.getInstance();
int heures=calendrier.get(Calendar.HOUR_OF_DAY);
int minutes=calendrier.get(Calendar.MINUTE);
int secondes=calendrier.get(Calendar.SECOND);
// godziny, minuty i sekundy są zmiennymi globalnymi
//, które będą mogły być wykorzystane w kodzie HTML
%>
<% // kod HTML %>
<html>
<head>
<title>Page JSP affichant l'heure</title>
</head>
<body>
<center>
<h1>Une page JSP générée dynamiquement</h1>
<h2>Il est <%=heures%>:<%=minutes%>:<%=secondes%></h2>
<br>
<h3>A chaque fois que vous rechargez la page, l'heure change</h3>
</body>
</html>
Po uruchomieniu przez serwer WWW skrypt ten generuje następującą stronę:

Testy
- umieścić skrypt heure.jsp w katalogu <tomcat>\jakarta-tomcat\webapps\examples\jsp (Tomcat 3.x) lub w katalogu <tomcat>\webapps\examples\jsp (Tomcat 4.x)
- uruchomić serwer Tomcat
- wywołać stronę URL pod adresem http://localhost:8080/examples/jsp/heure.jsp
2.5.6. Wnioski
Powyższe przykłady pokazały, że:
- strona HTML może być generowana dynamicznie przez program. Na tym właśnie polega programowanie internetowe.
- że wykorzystywane języki i serwery internetowe mogą być zróżnicowane. Obecnie obserwuje się następujące główne trendy:
- kombinacje Apache/PHP (Windows, Linux) oraz IIS/PHP (Windows)
- technologia ASP.NET na platformach Windows, łącząca serwer IIS z językiem .NET (C#, VB.NET, ...)
- technologia serwletów Java i stron JSP działająca z różnymi serwerami (Tomcat, Apache, IIS) oraz na różnych platformach (Windows, Linux). To właśnie ta ostatnia technologia zostanie szczegółowo omówiona w niniejszym dokumencie.
2.6. Skrypty po stronie przeglądarki
Strona HTML może zawierać skrypty, które będą wykonywane przez przeglądarkę. Istnieje wiele języków skryptowych po stronie przeglądarki. Oto kilka z nich:
Język | Obsługiwane przeglądarki |
VBScript | IE |
JavaScript | IE, Netscape |
PerlScript | IE |
Java | IE, Netscape |
Weźmy kilka przykładów.
2.6.1. Strona internetowa ze skryptem VBScript po stronie przeglądarki
Strona vbs1.html
<html>
<head>
<title>essai : une page web avec un script vb</title>
<script language="vbscript">
function reagir
alert "Vous avez cliqué sur le bouton OK"
end function
</script>
</head>
<body>
<center>
<h1>Une page Web avec un script VB</h1>
<table>
<tr>
<td>Cliquez sur le bouton</td>
<td><input type="button" value="OK" name="cmdOK" onclick="reagir"></td>
</tr>
</table>
</body>
</html>
Powyższa strona HTML zawiera nie tylko kod HTML, ale również program przeznaczony do wykonania przez przeglądarkę, która załaduje tę stronę. Kod wygląda następująco:
<script language="vbscript">
function reagir
alert "Vous avez cliqué sur le bouton OK"
end function
</script>
Tagi <script></script> służą do wyodrębniania skryptów na stronie HTML. Skrypty te mogą być napisane w różnych językach, a to opcja language w tagu <script> określa używany język. W tym przypadku jest to VBScript. Nie będziemy się tutaj zagłębiać w szczegóły tego języka. Powyższy skrypt definiuje funkcję o nazwie réagir, która wyświetla komunikat. Kiedy ta funkcja jest wywoływana? Wskazuje nam to następujący wiersz kodu HTML:
Atrybut onclick określa nazwę funkcji, która ma zostać wywołana, gdy użytkownik kliknie przycisk OK. Gdy przeglądarka załaduje tę stronę, a użytkownik kliknie przycisk OK, pojawi się następująca strona:

Testy
Tylko przeglądarka IE jest w stanie wykonywać skrypty VBScript. Przeglądarka Netscape wymaga do tego dodatkowych wtyczek. Można przeprowadzić następujące testy:
test1
- serwer Apache
- skrypt vbs1.html w <apache-DocumentRoot>
- wywołanie adresu URL http://localhost/vbs1.html za pomocą przeglądarki IE
test2
- serwer PWS
- skrypt vbs1.html w <pws-DocumentRoot>
- wywołaj adres URL http://localhost/vbs1.html za pomocą przeglądarki IE
2.6.2. Strona internetowa ze skryptem JavaScript po stronie przeglądarki
Strona: js1.html
<html>
<head>
<title>essai 4 : une page web avec un script Javascript</title>
<script language="javascript">
function reagir(){
alert ("Vous avez cliqué sur le bouton OK");
}
</script>
</head>
<body>
<center>
<h1>Une page Web avec un script Javascript</h1>
<table>
<tr>
<td>Cliquez sur le bouton</td>
<td><input type="button" value="OK" name="cmdOK" onclick="reagir()"></td>
</tr>
</table>
</body>
</html>
Mamy tu coś identycznego jak na poprzedniej stronie, z tą różnicą, że język VBScript zastąpiono językiem JavaScript. Ma on tę zaletę, że jest obsługiwany zarówno przez przeglądarkę IE, jak i Netscape. Jego wykonanie daje te same wyniki:

Testy
test1
- serwer Apache
- skrypt js1.html w <apache-DocumentRoot>
- wywołaj adres URL http://localhost/js1.html za pomocą przeglądarki IE lub Netscape
test2
- serwer PWS
- skrypt js1.html w <pws-DocumentRoot>
- wywołaj adres URL http://localhost/js1.html za pomocą przeglądarki IE lub Netscape
2.7. Komunikacja między klientem a serwerem
Wróćmy do naszego początkowego schematu, który ilustrował elementy składowe aplikacji internetowej:
![]() |
W tym miejscu skupiamy się na wymianie danych między komputerem klienckim a serwerem. Odbywa się ona za pośrednictwem sieci i warto przypomnieć ogólną strukturę wymiany danych między dwoma odległymi komputerami.
2.7.1. Model OSI
Model otwartej sieci o nazwie OSI (Open Systems Interconnection Reference Model), zdefiniowany przez ISO (Międzynarodową Organizację Normalizacyjną), opisuje idealną sieć, w której komunikację między komputerami można przedstawić za pomocą modelu siedmiowarstwowego:
![]() |
Każda warstwa korzysta z usług warstwy niższej i udostępnia swoje usługi warstwie wyższej. Załóżmy, że dwie aplikacje znajdujące się na różnych maszynach A i B chcą się komunikować: robią to na poziomie warstwy Application. Nie muszą one znać wszystkich szczegółów działania sieci: każda aplikacja przekazuje informacje, które chce przesłać, do warstwy poniżej – warstwy Présentation. Aplikacja musi zatem znać jedynie zasady współpracy z warstwą Présentation. Gdy informacja znajdzie się w warstwie Présentation, jest przekazywana zgodnie z innymi regułami do warstwy Session i tak dalej, aż informacja dotrze do nośnika fizycznego i zostanie fizycznie przesłana do komputera docelowego. Tam zostanie poddana procesowi odwrotnemu do tego, który miała miejsce na komputerze nadawczym.
Na każdej warstwie proces nadawczy odpowiedzialny za wysyłanie informacji przekazuje ją do procesu odbiorczego na innym komputerze należącym do tej samej warstwy. Odbywa się to zgodnie z określonymi zasadami, zwanymi protokołem warstwy. Otrzymujemy zatem następujący ostateczny schemat komunikacji:
![]() |
Rola poszczególnych warstw jest następująca:
Zapewnia transmisję bitów na nośniku fizycznym. W tej warstwie znajdują się urządzenia końcowe do przetwarzania danych (E.T.T.D.), takie jak terminal lub komputer, a także urządzenia końcowe obwodów danych (E.T.C.D.), takie jak modulator/demodulator, multiplekser, koncentrator. Istotne elementy na tym poziomie to: . wybór sposobu kodowania informacji (analogowego lub cyfrowego) . wybór trybu transmisji (synchroniczny lub asynchroniczny). | |
Ukrywa specyfikę warstwy fizycznej. Wykrywa i koryguje błędy transmisji. | |
Zarządza ścieżką, którą muszą podążać informacje wysyłane w sieci. Nazywa się to routage: określenie trasy, którą musi podążać informacja, aby dotarła do odbiorcy. | |
Umożliwia komunikację między dwiema aplikacjami, podczas gdy poprzednie warstwy pozwalały jedynie na komunikację między maszynami. Usługą świadczoną przez tę warstwę może być multipleksowanie: warstwa transportowa może wykorzystywać to samo połączenie sieciowe (między maszynami) do przesyłania informacji należących do kilku aplikacji. | |
W tej warstwie znajdują się usługi umożliwiające aplikacji otwarcie i utrzymanie sesji roboczej na zdalnym komputerze. | |
Ma ona na celu ujednolicenie sposobu przedstawiania danych na różnych komputerach. W ten sposób dane pochodzące z komputera A zostaną „przetworzone” przez warstwę Présentation komputera A zgodnie ze standardowym formatem, zanim zostaną wysłane do sieci. Po dotarciu do warstwy Présentation komputera docelowego B, który rozpozna je dzięki standardowemu formatowi, zostaną one przetworzone w inny sposób, aby aplikacja komputera B mogła je rozpoznać. | |
Na tym poziomie znajdują się aplikacje zazwyczaj bliskie użytkownikowi, takie jak poczta elektroniczna czy przesyłanie plików. |
2.7.2. Model TCP/IP
Model OSI jest modelem idealnym. Zestaw protokołów TCP/IP zbliża się do niego w następującej postaci:
![]() |
- interfejs sieciowy (karta sieciowa komputera) pełni funkcje warstw 1 i 2 modelu OSI
- warstwa IP (Internet Protocol) pełni funkcje warstwy 3 (sieć)
- warstwa TCP (Transfer Control Protocol) lub UDP (User Datagram Protocol) pełni funkcje warstwy 4 (transportowej). Protokół TCP zapewnia, że pakiety danych wymieniane między urządzeniami dotrą do miejsca przeznaczenia. Jeśli tak się nie stanie, odsyła zagubione pakiety. Protokół UDP nie wykonuje tej czynności, więc zadanie to spoczywa na programiście aplikacji. Dlatego w Internecie, który nie jest siecią w 100% niezawodną, najczęściej stosowany jest protokół TCP. Mówimy wówczas o sieci TCP-IP.
- Warstwa aplikacji obejmuje funkcje poziomów od 5 do 7 modelu OSI.
Aplikacje internetowe znajdują się w warstwie Application i opierają się zatem na protokołach TCP-IP. Warstwy Application na komputerach klienckich i serwerze wymieniają między sobą komunikaty, które są przekazywane warstwom od 1 do 4 modelu w celu dostarczenia do miejsca przeznaczenia. Aby się porozumieć, warstwy aplikacji obu komputerów muszą „mówić” tym samym językiem lub protokołem. Protokół aplikacji internetowych nosi nazwę HTTP (HyperText Transfer Protocol). Jest to protokół tekstowy, c.a.d, dzięki któremu urządzenia wymieniają między sobą wiersze tekstu w sieci, aby się porozumieć. Wymiana ta jest znormalizowana, co oznacza, że klient dysponuje pewną liczbą komunikatów, aby dokładnie wskazać serwerowi, czego oczekuje, a serwer również dysponuje pewną liczbą komunikatów, aby udzielić klientowi odpowiedzi. Ta wymiana komunikatów ma następującą postać:
![]() |
Klient --> Serwer
Gdy klient wysyła żądanie do serwera WWW, przesyła
- wiersze tekstu w formacie HTTP, aby wskazać, czego oczekuje
- pustą linię
- opcjonalnie dokument
Serwer --> Klient
Gdy serwer wysyła odpowiedź do klienta, przesyła
- wiersze tekstu w formacie HTTP, aby wskazać, co wysyła
- pusty wiersz
- opcjonalnie dokument
Wymiana danych ma zatem tę samą formę w obu kierunkach. W obu przypadkach może nastąpić wysłanie dokumentu, nawet jeśli rzadko zdarza się, by klient wysyłał dokument do serwera. Jednak protokół HTTP to przewiduje. To właśnie pozwala na przykład abonentom dostawcy usług internetowych na pobieranie różnych dokumentów na swoją stronę osobistą hostowaną u tego dostawcy. Wymieniane dokumenty mogą być dowolne. Weźmy na przykład przeglądarkę żądającą strony internetowej zawierającej obrazy:
- przeglądarka łączy się z serwerem internetowym i żąda żądanej strony. Żądane zasoby są jednoznacznie identyfikowane za pomocą URL (Uniform Resource Locator). Przeglądarka wysyła jedynie nagłówki HTTP, a nie sam dokument.
- Serwer odpowiada na to żądanie. Najpierw wysyła nagłówki HTTP, wskazujące, jaki typ odpowiedzi wysyła. Może to być komunikat o błędzie, jeśli żądana strona nie istnieje. Jeśli strona istnieje, serwer poinformuje w nagłówkach HTTP swojej odpowiedzi, że po nich wyśle dokument HTML (HyperText Markup Language). Dokument ten stanowi ciąg wierszy tekstu w formacie HTML. Tekst HTML zawiera znaczniki (tagi), które dostarczają przeglądarce wskazówek dotyczących sposobu wyświetlania tekstu.
- Klient na podstawie nagłówków HTTP wysłanych przez serwer wie, że otrzyma dokument HTML. Przeanalizuje go i być może zauważy, że zawiera odniesienia do obrazów. Obrazy te nie znajdują się w dokumencie HTML. W związku z tym wysyła nowe żądanie do tego samego serwera WWW, prosząc o pierwszy potrzebny mu obraz. Żądanie to jest identyczne z tym wysłanym w punkcie 1, z tą różnicą, że żądany zasób jest inny. Serwer przetworzy to żądanie, wysyłając klientowi żądany obraz. Tym razem w odpowiedzi nagłówki HTTP będą wskazywać, że wysłany plik to obraz, a nie dokument HTML.
- Klient pobiera przesłany obraz. Etapy 3 i 4 będą powtarzane, dopóki klient (zazwyczaj przeglądarka) nie otrzyma wszystkich dokumentów umożliwiających wyświetlenie całej strony.
2.7.3. Protokół HTTP
Przyjrzyjmy się protokołowi HTTP na przykładach. Jakie dane wymieniają między sobą przeglądarka i serwer WWW?
2.7.3.1. Odpowiedź serwera HTTP
Zobaczymy tutaj, w jaki sposób serwer internetowy odpowiada na żądania swoich klientów. Serwis internetowy lub serwis HTTP to serwis TCP-IP, który zazwyczaj działa na porcie 80. Może jednak działać na innym porcie. W takim przypadku przeglądarka klienta musiałaby podać ten port w żądaniu URL. Żądanie URL ma ogólną postać:
z
protokołem | HTTP dla serwisu internetowego. Przeglądarka może również pełnić rolę klienta usług FTP, news, telnet itp. |
nazwa | nazwa komputera, na którym działa usługa internetowa |
port | port serwisu internetowego. Jeśli jest to 80, można pominąć numer portu. Jest to najczęstszy przypadek |
ścieżka | ścieżka wskazująca żądany zasób |
informacje | dodatkowe informacje przekazywane serwerowi w celu doprecyzowania żądania klienta |
Co robi przeglądarka, gdy użytkownik żąda załadowania pliku URL?
- otwiera połączenie TCP-IP z maszyną i portem wskazanymi w części machine[:port] pliku URL. Nawiązanie połączenia TCP-IP oznacza utworzenie „kanału” komunikacyjnego między dwoma maszynami. Po utworzeniu tego kanału wszystkie informacje wymieniane między tymi maszynami będą przez niego przepływać. Utworzenie tego kanału TCP-IP nie wiąże się jeszcze z wykorzystaniem protokołu internetowego HTTP.
- Po utworzeniu kanału TCP-IP klient wyśle żądanie do serwera internetowego, wysyłając mu wiersze tekstu (polecenia) w formacie HTTP. Wyśle on do serwera część ścieżki/informacji z URL
- serwer odpowie w ten sam sposób i w tym samym kanale
- jeden z partnerów podejmie decyzję o zamknięciu kanału. Zależy to od używanego protokołu HTTP. W przypadku protokołu HTTP 1.0 serwer zamyka połączenie po każdej swojej odpowiedzi. Zmusza to klienta, który musi wysłać kilka żądań w celu uzyskania różnych dokumentów tworzących stronę internetową, do nawiązywania nowego połączenia przy każdym żądaniu, co wiąże się z pewnymi kosztami. W przypadku protokołu HTTP/1.1 klient może poinstruować serwer, aby utrzymywał połączenie otwarte do momentu, aż klient poleci jego zamknięcie. Dzięki temu może pobrać wszystkie dokumenty strony internetowej za pomocą jednego połączenia i samodzielnie zamknąć je po otrzymaniu ostatniego dokumentu. Serwer wykryje to zamknięcie i również zamknie połączenie.
Aby zapoznać się z wymianą danych między klientem a serwerem internetowym, wykorzystamy generyczny klient TCP. Jest to program, który może pełnić rolę klienta dowolnej usługi wykorzystującej protokół komunikacyjny oparty na wierszach tekstowych, tak jak ma to miejsce w przypadku protokołu HTTP. Wiersze tekstowe będą wpisywane przez użytkownika za pomocą klawiatury. Wymaga to od niego znajomości protokołu komunikacyjnego usługi, z którą próbuje się połączyć. Odpowiedź serwera jest następnie wyświetlana na ekranie. Program został napisany w języku Java i znajduje się w załączniku. Używamy go tutaj w oknie DOS w systemie Windows i uruchamiamy go w następujący sposób:
z
nazwa | nazwa komputera, na którym działa usługa, z którą chcemy się połączyć |
port | port, na którym usługa jest udostępniana |
Na podstawie tych dwóch informacji program nawiąże połączenie o nazwie TCP-IP z wskazaną maszyną i portem. Połączenie to posłuży do wymiany wierszy tekstu między klientem a serwerem internetowym. Wiersze po stronie klienta są wpisywane przez użytkownika za pomocą klawiatury i wysyłane do serwera. Wiersze tekstowe zwracane przez serwer w odpowiedzi są wyświetlane na ekranie. W ten sposób może nawiązać się bezpośredni dialog między użytkownikiem korzystającym z klawiatury a serwerem internetowym. Wypróbujmy to na już przedstawionych przykładach. Utworzyliśmy następującą statyczną stronę o nazwie HTML:
<html>
<head>
<title>essai 1 : une page statique</title>
</head>
<body>
<center>
<h1>Une page statique...</h1>
</body>
</html>
które wyświetlamy w przeglądarce:

Widać, że żądany adres URL to: http://localhost:81/essais/essai1.html. Serwer usługi internetowej to zatem localhost (=serwer lokalny), a port to 81. Jeśli poprosimy o wyświetlenie tekstu HTML tej strony internetowej (Widok/Źródło), znajdziemy tekst HTML utworzony początkowo:

Teraz użyjmy naszego ogólnego klienta TCP, aby zażądać tego samego URL:
Dos>java clientTCPgenerique localhost 81
Commandes :
GET /essais/essai1.html HTTP/1.0
<-- HTTP/1.1 200 OK
<-- Date: Mon, 08 Jul 2002 08:07:46 GMT
<-- Server: Apache/1.3.24 (Win32) PHP/4.2.0
<-- Last-Modified: Mon, 08 Jul 2002 08:00:30 GMT
<-- ETag: "0-a1-3d29469e"
<-- Accept-Ranges: bytes
<-- Content-Length: 161
<-- Connection: close
<-- Content-Type: text/html
<--
<-- <html>
<-- <head>
<-- <title>essai 1 : une page statique</title>
<-- </head>
<-- <body>
<-- <center>
<-- <h1>Une page statique...</h1>
<-- </body>
<-- </html>
Po uruchomieniu klienta za pomocą polecenia java clientTCPgenerique localhost 81 utworzono połączenie między programem a serwerem WWW działającym na tej samej maszynie (localhost) na porcie 81. Można rozpocząć wymianę danych między klientem a serwerem w formacie HTTP. Przypomnijmy, że składają się one z trzech elementów:
- nagłówki HTTP
- pusta linia
- dane opcjonalne
W naszym przykładzie klient wysyła tylko jedno żądanie:
GET /essais/essai1.html HTTP/1.0
Ten wiersz składa się z trzech elementów:
polecenie HTTP służące do żądania zasobu. Istnieją również inne: HEAD żąda zasobu, ale ogranicza się do nagłówków HTTP zawartych w odpowiedzi serwera. Sam zasób nie jest wysyłany. PUT umożliwia klientowi wysłanie dokumentu do serwera | |
żądany zasób | |
poziom używanego protokołu HTTP. W tym przypadku 1.0. Oznacza to, że serwer zamknie połączenie, gdy tylko wyśle swoją odpowiedź |
Po nagłówkach HTTP zawsze musi następować pusty wiersz. Tak właśnie postąpił tutaj klient. W ten sposób klient lub serwer wie, że część HTTP wymiany została zakończona. W tym momencie dla klienta wszystko jest zakończone. Nie ma on żadnego dokumentu do wysłania. Następnie rozpoczyna się odpowiedź serwera, składająca się w naszym przykładzie ze wszystkich wierszy zaczynających się od znaku <--. Najpierw wysyła serwer serię nagłówków HTTP, po których następuje pusty wiersz:
<-- HTTP/1.1 200 OK
<-- Date: Mon, 08 Jul 2002 08:07:46 GMT
<-- Server: Apache/1.3.24 (Win32) PHP/4.2.0
<-- Last-Modified: Mon, 08 Jul 2002 08:00:30 GMT
<-- ETag: "0-a1-3d29469e"
<-- Accept-Ranges: bytes
<-- Content-Length: 161
<-- Connection: close
<-- Content-Type: text/html
<--
serwer informuje,
| |
data i godzina odpowiedzi | |
serwer podaje swoje dane identyfikacyjne. W tym przypadku jest to serwer Apache | |
data ostatniej modyfikacji zasobu, o który poprosił klient | |
... | |
jednostka miary wysłanych danych. W tym przypadku bajt (byte) | |
liczba bajtów dokumentu, który zostanie wysłany po nagłówkach HTTP. Liczba ta odpowiada w rzeczywistości rozmiarowi pliku w bajtach essai1.html: | |
serwer informuje, że zamknie połączenie po wysłaniu dokumentu | |
serwer informuje, że wyśle tekst (text) w formacie HTML (html). |
Klient odbiera te nagłówki HTTP i wie już, że otrzyma 161 bajtów reprezentujących dokument HTML. Serwer wysyła te 161 bajtów bezpośrednio po pustej linii, która sygnalizowała koniec nagłówków HTTP:
<-- <html>
<-- <head>
<-- <title>essai 1 : une page statique</title>
<-- </head>
<-- <body>
<-- <center>
<-- <h1>Une page statique...</h1>
<-- </body>
<-- </html>
Rozpoznajemy tu plik HTML utworzony na początku. Gdyby naszym klientem była przeglądarka, po odebraniu tych wierszy tekstu zinterpretowałaby je, aby wyświetlić użytkownikowi korzystającemu z klawiatury następującą stronę:

Wykorzystajmy ponownie naszego generycznego klienta TCP, aby zażądać tego samego zasobu, ale tym razem za pomocą polecenia HEAD, które żąda wyłącznie nagłówków odpowiedzi:
Dos>java.bat clientTCPgenerique localhost 81
Commandes :
HEAD /essais/essai1.html HTTP/1.1
Host: localhost:81
<-- HTTP/1.1 200 OK
<-- Date: Mon, 08 Jul 2002 09:07:25 GMT
<-- Server: Apache/1.3.24 (Win32) PHP/4.2.0
<-- Last-Modified: Mon, 08 Jul 2002 08:00:30 GMT
<-- ETag: "0-a1-3d29469e"
<-- Accept-Ranges: bytes
<-- Content-Length: 161
<-- Content-Type: text/html
<--
Otrzymujemy ten sam wynik co poprzednio, bez dokumentu HTML. Należy zauważyć, że w swoim żądaniu HEAD klient wskazał, że korzysta z protokołu HTTP w wersji 1.1. Wymusza to na nim wysłanie drugiego nagłówka HTTP, określającego parę machine:port, którą klient chce wywołać: Host: localhost:81.
Teraz spróbujmy pobrać obraz zarówno za pomocą przeglądarki, jak i za pomocą ogólnego klienta TCP. Najpierw za pomocą przeglądarki:

Plik univ01.gif ma 3167 bajtów:
Teraz skorzystajmy z ogólnego klienta TCP:
E:\data\serge\JAVA\SOCKETS\client générique>java clientTCPgenerique localhost 81
Commandes :
HEAD /images/univ01.gif HTTP/1.1
host: localhost:81
<-- HTTP/1.1 200 OK
<-- Date: Tue, 09 Jul 2002 13:53:24 GMT
<-- Server: Apache/1.3.24 (Win32) PHP/4.2.0
<-- Last-Modified: Fri, 14 Apr 2000 11:37:42 GMT
<-- ETag: "0-c5f-38f70306"
<-- Accept-Ranges: bytes
<-- Content-Length: 3167
<-- Content-Type: image/gif
<--
W odpowiedzi serwera należy zwrócić uwagę na następujące elementy:
| |
| |
|
2.7.3.2. Żądanie klienta HTTP
Zadajmy sobie teraz następujące pytanie: jeśli chcemy napisać program, który „komunikuje się” z serwerem WWW, jakie polecenia musi on wysłać do serwera WWW, aby uzyskać określony zasób? W poprzednich przykładach znaleźliśmy wstępną odpowiedź. Spotkaliśmy się z trzema poleceniami:
| |
| |
|
Istnieją również inne polecenia. Aby je poznać, skorzystamy teraz z ogólnego serwera TCP. Jest to program napisany w języku Java, który również znajdziecie w załączniku. Uruchamia się go poleceniem: java serveurTCPgenerique portEcoute, gdzie portEcoute to port, z którym klienci muszą się połączyć. Program serveurTCPgenerique
- wyświetla na ekranie polecenia wysłane przez klientów
- i wysyła im w odpowiedzi wiersze tekstu wpisane przez użytkownika na klawiaturze. To właśnie ten program pełni rolę serwera. W naszym przykładzie użytkownik korzystający z klawiatury będzie pełnił rolę serwisu internetowego.
Zsymulujmy teraz serwer internetowy, uruchamiając nasz serwer ogólnego przeznaczenia na porcie 88:
Dos> java serveurTCPgenerique 88
Serveur générique lancé sur le port 88
Otwórzmy teraz przeglądarkę i wywołajmy adres http://localhost:88/exemple.html. Przeglądarka połączy się wówczas z portem 88 na serwerze localhost, a następnie zażąda strony /exemple.html:

Przyjrzyjmy się teraz oknu naszego serwera, które wyświetla dane przesłane przez klienta (niektóre wiersze związane z działaniem programu serveurTCPgenerique zostały pominięte w celu uproszczenia):
Dos>java serveurTCPgenerique 88
Serveur générique lancé sur le port 88
...
<-- GET /exemple.html HTTP/1.1
<-- Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, */*
<-- Accept-Language: fr
<-- Accept-Encoding: gzip, deflate
<-- User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.0.2 914)
<-- Host: localhost:88
<-- Connection: Keep-Alive
<--
Wiersze poprzedzone znakiem <-- to te wysłane przez klienta. W ten sposób odkrywamy nagłówki HTTP, z którymi jeszcze się nie spotkaliśmy:
| |
| |
| |
| |
|
Nagłówki HTTP wysyłane przez przeglądarkę kończą się pustym wierszem, zgodnie z oczekiwaniami.
Przygotujmy odpowiedź dla naszego klienta. Użytkownik korzystający z klawiatury jest tutaj prawdziwym serwerem i może ręcznie przygotować odpowiedź. Przypomnijmy sobie odpowiedź wysłaną przez serwer WWW w poprzednim przykładzie:
<-- HTTP/1.1 200 OK
<-- Date: Mon, 08 Jul 2002 08:07:46 GMT
<-- Server: Apache/1.3.24 (Win32) PHP/4.2.0
<-- Last-Modified: Mon, 08 Jul 2002 08:00:30 GMT
<-- ETag: "0-a1-3d29469e"
<-- Accept-Ranges: bytes
<-- Content-Length: 161
<-- Connection: close
<-- Content-Type: text/html
<--
<-- <html>
<-- <head>
<-- <title>essai 1 : une page statique</title>
<-- </head>
<-- <body>
<-- <center>
<-- <h1>Une page statique...</h1>
<-- </body>
<-- </html>
Spróbujmy ręcznie (na klawiaturze) stworzyć podobną odpowiedź. Wiersze zaczynające się od --> : są wysyłane do klienta:
...
<-- Host: localhost:88
<-- Connection: Keep-Alive
<--
--> : HTTP/1.1 200 OK
--> : Server: serveur tcp generique
--> : Connection: close
--> : Content-Type: text/html
--> :
--> : <html>
--> : <head><title>Serveur generique</title></head>
--> : <body>
--> : <center>
--> : <h2>Reponse du serveur generique</h2>
--> : </center>
--> : </body>
--> : </html>
fin
Polecenie fin jest związane z działaniem programu serveurTCPgenerique. Zatrzymuje ono wykonywanie programu i zamyka połączenie między serwerem a klientem. W naszej odpowiedzi ograniczyliśmy się do następujących nagłówków HTTP:
HTTP/1.1 200 OK
--> : Server: serveur tcp generique
--> : Connection: close
--> : Content-Type: text/html
--> :
Nie podajemy rozmiaru pliku, który zamierzamy wysłać (Content-Length), a jedynie informujemy, że po jego wysłaniu zamkniemy połączenie (Connection: close). To wystarczy dla przeglądarki. Gdy przeglądarka zauważy, że połączenie zostało zamknięte, uzna, że odpowiedź serwera została zakończona i wyświetli stronę HTML, która została jej przesłana. Wygląda ona następująco:
--> : <html>
--> : <head><title>Serveur generique</title></head>
--> : <body>
--> : <center>
--> : <h2>Reponse du serveur generique</h2>
--> : </center>
--> : </body>
--> : </html>
Przeglądarka wyświetla wówczas następującą stronę:

Jeśli w powyższym przykładzie wpiszemy View/Source, aby sprawdzić, co otrzymała przeglądarka, otrzymamy:

czyli dokładnie to, co wysłaliśmy z serwera generycznego.
2.8. Język HTML
Przeglądarka internetowa może wyświetlać różne dokumenty, z których najpopularniejszym jest dokument HTML (HyperText Markup Language). Jest to tekst sformatowany za pomocą znaczników o postaci <balise>texte</balise>. Na przykład tekst <B>important</B> wyświetli ważny fragment tekstu pogrubioną czcionką. Istnieją również pojedyncze znaczniki, takie jak znacznik <hr>, który wyświetla poziomą linię. Nie będziemy omawiać wszystkich znaczników, jakie można znaleźć w tekście HTML. Istnieje wiele programów WYSIWYG, które pozwalają na stworzenie strony internetowej bez pisania ani jednej linii kodu HTML. Narzędzia te automatycznie generują kod HTML na podstawie układu strony utworzonego za pomocą myszki i gotowych elementów sterujących. Można więc wstawić (za pomocą myszki) do strony tabelę, a następnie przejrzeć kod HTML wygenerowany przez oprogramowanie, aby dowiedzieć się, jakich tagów należy użyć do zdefiniowania tabeli na stronie internetowej. To naprawdę nie jest skomplikowane. Ponadto znajomość języka HTML jest niezbędna, ponieważ dynamiczne aplikacje internetowe muszą samodzielnie generować kod HTML, który ma być wysyłany do klientów internetowych. Kod ten jest generowany programowo i oczywiście trzeba wiedzieć, co należy wygenerować, aby klient otrzymał stronę internetową, której oczekuje.
Podsumowując, nie ma potrzeby znajomości całego języka HTML, aby rozpocząć programowanie internetowe. Jednak znajomość ta jest niezbędna i można ją zdobyć poprzez korzystanie z oprogramowania do tworzenia stron internetowych, takiego jak Word, FrontPage, DreamWeaver i dziesiątek innych. Innym sposobem na poznanie subtelności języka HTML jest przeglądanie sieci i wyświetlanie kodu źródłowego stron, które zawierają interesujące i jeszcze nieznane Ci funkcje.
2.8.1. Przykład
Rozważmy poniższy przykład, utworzony za pomocą FrontPage Express, bezpłatnego narzędzia dołączonego do przeglądarki Internet Explorer. Kod wygenerowany przez FrontPage został tutaj uproszczony. Przykład ten przedstawia kilka elementów, które można znaleźć w dokumencie internetowym, takich jak:
- tabela
- obraz
- link

Dokument HTML ma ogólną postać:
Cały dokument jest ujęty w tagi <html>...</html>. Składa się on z dwóch części:
- <head>...</head>: jest to niewidoczna część dokumentu. Zawiera informacje dla przeglądarki, która wyświetli dokument. Często znajduje się tam tag <title>...</title>, który określa tekst, jaki zostanie wyświetlony w pasku tytułu przeglądarki. Można tam również znaleźć inne tagi, w szczególności te definiujące słowa kluczowe dokumentu, wykorzystywane następnie przez wyszukiwarki. W tej części można również znaleźć skrypty, najczęściej napisane w języku JavaScript lub VBScript, które zostaną wykonane przez przeglądarkę.
- <body atrybuty>...</body>: jest to część, która zostanie wyświetlona przez przeglądarkę. Tagi zawarte w tej części wskazują przeglądarce „pożądany” wygląd dokumentu. Każda przeglądarka interpretuje te tagi na swój sposób. W związku z tym dwie przeglądarki mogą wyświetlać ten sam dokument internetowy w różny sposób. Jest to zazwyczaj jeden z problemów, z którymi borykają się projektanci stron internetowych.
Kod HTML naszego przykładowego dokumentu wygląda następująco:
<html>
<head>
<title>balises</title>
</head>
<body background="/images/standard.jpg">
<center>
<h1>Les balises HTML</h1>
<hr>
</center>
<table border="1">
<tr>
<td>cellule(1,1)</td>
<td valign="middle" align="center" width="150">cellule(1,2)</td>
<td>cellule(1,3)</td>
</tr>
<tr>
<td>cellule(2,1)</td>
<td>cellule(2,2)</td>
<td>cellule(2,3</td>
</tr>
</table>
<table border="0">
<tr>
<td>Une image</td>
<td><img border="0" src="/images/univ01.gif" width="80" height="95"></td>
</tr>
<tr>
<td>le site de l'ISTIA</td>
<td><a href="http://istia.univ-angers.fr">ici</a></td>
</tr>
</table>
</body>
</html>
W kodzie zaznaczono wyłącznie te elementy, które nas interesują:
Element | tagi i przykłady HTML |
<title>balises</title> balises pojawi się w pasku tytułu przeglądarki wyświetlającej dokument | |
<hr>: wyświetla poziomą kreskę | |
<atrybuty tabeli>....</table>: w celu zdefiniowania tabeli <tr atrybuty>...</tr>: służy do zdefiniowania wiersza <td atrybuty>...</td>: do zdefiniowania komórki przykłady: <table border="1">...</table>: atrybut border określa grubość obramowania tabeli <td valign="middle" align="center" width="150">komórka(1,2)</td>: definiuje komórkę, której zawartością będzie komórka(1,2). Zawartość ta zostanie wyśrodkowana pionowo (valign="middle") i poziomo (align="center"). Komórka będzie miała szerokość 150 pikseli (width="150") | |
<img border="0" src="/images/univ01.gif" width="80" height="95">: definiuje obraz bez obramowania (border="0"), o wysokości 95 pikseli (height="95"), o szerokości 80 pikseli (width="80"), którego plik źródłowy znajduje się pod adresem /images/univ01.gif na serwerze internetowym (src="/images/univ01.gif"). Link ten znajduje się w dokumencie internetowym, który został wygenerowany za pomocą narzędzia URL http://localhost:81/html/balises.htm. W związku z tym przeglądarka zażąda pliku URL http://localhost:81/images/univ01.gif, aby pobrać obraz, do którego odwołuje się ten link. | |
<a href="http://istia.univ-angers.fr">tutaj</a>: sprawia, że tekst ici służy jako link do strony URL http://istia.univ-angers.fr. | |
<body background="/images/standard.jpg">: oznacza, że obraz, który ma służyć jako tło strony, znajduje się pod adresem URL /images/standard.jpg na serwerze internetowym. W kontekście naszego przykładu przeglądarka wyśle żądanie do adresu URL http://localhost:81/images/standard.jpg, aby pobrać ten obraz tła. |
Na tym prostym przykładzie widać, że aby zbudować cały dokument, przeglądarka musi wysłać trzy żądania do serwera:
- http://localhost:81/html/balises.htm, aby pobrać kod źródłowy HTML dokumentu
- http://localhost:81/images/univ01.gif, aby pobrać obraz univ01.gif
- http://localhost:81/images/standard.jpg, aby uzyskać obraz tła o numerze standard.jpg
Poniższy przykład przedstawia formularz internetowy, który również został utworzony przy użyciu FrontPage.

Kod HTML wygenerowany przez FrontPage i nieco uproszczony wygląda następująco:
<html>
<head>
<title>balises</title>
<script language="JavaScript">
function effacer(){
alert("Vous avez cliqué sur le bouton Effacer");
}//usuń
</script>
</head>
<body background="/images/standard.jpg">
<form method="POST" >
<table border="0">
<tr>
<td>Etes-vous marié(e)</td>
<td>
<input type="radio" value="Oui" name="R1">Oui
<input type="radio" name="R1" value="non" checked>Non
</td>
</tr>
<tr>
<td>Cases à cocher</td>
<td>
<input type="checkbox" name="C1" value="un">1
<input type="checkbox" name="C2" value="deux" checked>2
<input type="checkbox" name="C3" value="trois">3
</td>
</tr>
<tr>
<td>Champ de saisie</td>
<td>
<input type="text" name="txtSaisie" size="20" value="qqs mots">
</td>
</tr>
<tr>
<td>Mot de passe</td>
<td>
<input type="password" name="txtMdp" size="20" value="unMotDePasse">
</td>
</tr>
<tr>
<td>Boîte de saisie</td>
<td>
<textarea rows="2" name="areaSaisie" cols="20">
ligne1
ligne2
ligne3
</textarea>
</td>
</tr>
<tr>
<td>combo</td>
<td>
<select size="1" name="cmbValeurs">
<option>choix1</option>
<option selected>choix2</option>
<option>choix3</option>
</select>
</td>
</tr>
<tr>
<td>liste à choix simple</td>
<td>
<select size="3" name="lst1">
<option selected>liste1</option>
<option>liste2</option>
<option>liste3</option>
<option>liste4</option>
<option>liste5</option>
</select>
</td>
</tr>
<tr>
<td>liste à choix multiple</td>
<td>
<select size="3" name="lst2" multiple>
<option>liste1</option>
<option>liste2</option>
<option selected>liste3</option>
<option>liste4</option>
<option>liste5</option>
</select>
</td>
</tr>
<tr>
<td>bouton</td>
<td>
<input type="button" value="Effacer" name="cmdEffacer" onclick="effacer()">
</td>
</tr>
<tr>
<td>envoyer</td>
<td>
<input type="submit" value="Envoyer" name="cmdRenvoyer">
</td>
</tr>
<tr>
<td>rétablir</td>
<td>
<input type="reset" value="Rétablir" name="cmdRétablir">
</td>
</tr>
</table>
<input type="hidden" name="secret" value="uneValeur">
</form>
</body>
</html>
Związek między kontrolą wizualną <--> znacznikiem HTML jest następujący:
Kontrola | tag HTML |
<form method="POST" > | |
<input type="text" name="txtSaisie" size="20" value="kilka słów"> | |
<input type="password" name="txtMdp" size="20" value="unMotDePasse"> | |
<textarea rows="2" name="areaSaisie" cols="20"> wiersz1 wiersz 2 wiersz 3 </textarea> | |
<input type="radio" value="Tak" name="R1">Tak <input type="radio" name="R1" value="nie" checked>Nie | |
<input type="checkbox" name="C1" value="jeden">1 <input type="checkbox" name="C2" value="dwa" checked>2 <input type="checkbox" name="C3" value="trzy">3 | |
<select size="1" name="cmbValeurs"> <option>opcja1</option> <option selected>opcja 2</option> <option>opcja 3</option> </select> | |
<select size="3" name="lst1"> <option selected>lista1</option> <option>lista2</option> <option>lista3</option> <option>lista4</option> <option>lista5</option> </select> | |
<select size="3" name="lst2" multiple> <option>lista1</option> <option>lista2</option> <option selected>lista3</option> <option>lista4</option> <option>lista5</option> </select> | |
<input type="submit" value="Wyślij" name="cmdRenvoyer"> | |
<input type="reset" value="Przywróć" name="cmdRétablir"> | |
<input type="button" value="Usuń" name="cmdEffacer" onclick="effacer()"> |
Przyjrzyjmy się tym różnym elementom sterującym.
2.8.1.1. Formularz
<form method="POST" > |
<form name="..." method="..." action="...">...</form> | |
name="frmexemple": nazwa formularza method="..." : metoda używana przez przeglądarkę do wysyłania na serwer WWW wartości zebranych w formularzu action="..." : adres, na który zostaną wysłane wartości zebrane w formularzu. Formularz internetowy jest otoczony tagami <form>...</form>. Formularz może mieć nazwę (name="xx"). Dotyczy to wszystkich elementów kontrolnych, które można znaleźć w formularzu. Nazwa ta jest przydatna, jeśli dokument internetowy zawiera skrypty, które muszą odwoływać się do elementów formularza. Celem formularza jest zebranie informacji podanych przez użytkownika za pomocą klawiatury lub myszy oraz przesłanie ich do serwera internetowego o adresie URL. Którego? Tego, do którego odwołuje się atrybut action="URL". Jeśli ten atrybut nie występuje, informacje zostaną wysłane na serwer URL dokumentu, w którym znajduje się formularz. Tak byłoby w przypadku powyższego przykładu. Do tej pory zawsze postrzegaliśmy klienta internetowego jako „żądającego” informacji od serwera internetowego, a nigdy jako „przekazującego” mu informacje. W jaki sposób klient internetowy przekazuje informacje (zawarte w formularzu) do serwera internetowego? Omówimy to szczegółowo nieco później. Może on skorzystać z dwóch różnych metod o nazwach POST i GET. Atrybut method="méthode", z metodą równą GET lub POST, w tagu <form> wskazuje przeglądarce metodę, jaką należy zastosować do wysłania informacji zebranych w formularzu do adresu URL określonego przez atrybut action="URL". Gdy atrybut method nie jest określony, domyślnie stosowana jest metoda GET. |
2.8.1.2. Pole wprowadzania danych
![]()
![]()
<input type="text" name="txtSaisie" size="20" value="kilka słów"> <input type="password" name="txtMdp" size="20" value="unMotDePasse"> |
<input type="..." name="..." size=".." value=".."> Tag `input` służy do różnych elementów sterujących. To właśnie atrybut type pozwala odróżnić te różne elementy sterujące od siebie. | |
type="text": określa, że jest to pole wprowadzania danych type="password": znaki w polu wprowadzania danych są zastępowane znakami *. To jedyna różnica w stosunku do zwykłego pola wprowadzania danych. Ten typ elementu kontrolnego nadaje się do wprowadzania haseł. size="20": liczba znaków widocznych w polu – nie uniemożliwia wprowadzenia większej liczby znaków name="txtSaisie": nazwa elementu sterującego value="kilka słów": tekst, który będzie wyświetlany w polu wprowadzania danych. |
2.8.1.3. Pole wprowadzania wielowierszowe
![]()
<textarea rows="2" name="areaSaisie" cols="20"> ligne1 ligne2 ligne3 </textarea> |
<textarea ...>tekst</textarea> wyświetla wielowierszowe pole wprowadzania tekstu, w którym początkowo znajduje się tekst | |
rows="2": liczba wierszy cols="'20" : liczba kolumn name="areaSaisie": nazwa kontrolki |
2.8.1.4. Przyciski opcji
![]()
<input type="radio" value="Tak" name="R1">Tak <input type="radio" name="R1" value="nie" checked>Nie |
<input type="radio" attribut2="valeur2" ....>tekst wyświetla przycisk opcji z tekstem obok. | |
name="radio": nazwa elementu sterującego. Przyciski opcji o tej samej nazwie tworzą grupę przycisków, które wykluczają się wzajemnie: można zaznaczyć tylko jeden z nich. value="wartość": wartość przypisana do przycisku opcji. Nie należy mylić tej wartości z tekstem wyświetlanym obok przycisku opcji. Ten ostatni służy wyłącznie do wyświetlania. checked: jeśli to słowo kluczowe jest obecne, przycisk opcji jest zaznaczony, w przeciwnym razie nie jest. |
2.8.1.5. Pola wyboru
<input type="checkbox" name="C1" value="jeden">1 <input type="checkbox" name="C2" value="dwa" checked>2 <input type="checkbox" name="C3" value="trzy">3 |
![]()
<input type="checkbox" attribut2="valeur2" ....>tekst wyświetla pole wyboru z tekstem obok. | |
name="C1": nazwa elementu sterującego. Pola wyboru mogą, ale nie muszą mieć tę samą nazwę. Pola o tej samej nazwie tworzą grupę powiązanych pól. value="wartość": wartość przypisana do pola wyboru. Nie należy mylić tej wartości z tekstem wyświetlanym obok przycisku opcji. Ten ostatni służy wyłącznie do wyświetlania. checked: jeśli to słowo kluczowe występuje, przycisk opcji jest zaznaczony, w przeciwnym razie nie jest. |
2.8.1.6. Lista rozwijana (combo)
<select size="1" name="cmbValeurs"> <option>choix1</option> <option selected>opcja2</option> <option>choix3</option> </select> |
![]()
<select size=".." name=".."> <option [selected]>...</option> ... </select> wyświetla na liście teksty zawarte między tagami <option>...</option> | |
name="cmbValeurs": nazwa kontrolki. size="1": liczba widocznych elementów listy. size="1" sprawia, że lista działa jak pole kombi. selected: jeśli to słowo kluczowe występuje dla elementu listy, element ten pojawia się jako zaznaczony na liście. W naszym przykładzie powyżej element listy choix2 pojawia się jako zaznaczony element listy rozwijanej, gdy jest ona wyświetlana po raz pierwszy. |
2.8.1.7. Lista z jednym elementem do wyboru
<select size="3" name="lst1"> <option selected>lista1</option> <option>liste2</option> <option>liste3</option> <option>liste4</option> <option>liste5</option> </select> |

<select size=".." name=".."> <option [selected]>...</option> ... </select> wyświetla na liście teksty zawarte między tagami <option>...</option> | |
takie same jak w przypadku listy rozwijanej wyświetlającej tylko jeden element. Ten element sterujący różni się od poprzedniej listy rozwijanej jedynie atrybutem size>1. |
2.8.1.8. Lista z możliwością wielokrotnego wyboru
<select size="3" name="lst2" multiple> <option selected>lista1</option> <option>liste2</option> <option selected>lista3</option> <option>liste4</option> <option>liste5</option> </select> |

<select size=".." name=".." multiple> <option [selected]>...</option> ... </select> wyświetla na liście teksty zawarte między tagami <option>...</option> | |
multiple: umożliwia zaznaczenie wielu elementów z listy. W powyższym przykładzie zaznaczone są zarówno elementy liste1, jak i liste3. |
2.8.1.9. Przycisk typu button
<input type="button" value="Usuń" name="cmdEffacer" onclick="effacer()"> |
![]()
<input type="button" value="..." name="..." onclick="effacer()" ....> | |
type="button": definiuje kontrolkę przycisku. Istnieją dwa inne typy przycisków: submit i reset. value="Usuń": tekst wyświetlany na przycisku onclick="funkcja()": pozwala zdefiniować funkcję, która ma zostać wykonana, gdy użytkownik kliknie przycisk. Funkcja ta jest częścią skryptów zdefiniowanych w wyświetlanym dokumencie internetowym. Powyższa składnia jest zgodna ze standardem javascript. Jeśli skrypty są napisane w języku VBScript, należy wpisać onclick="funkcja" bez nawiasów. Składnia pozostaje taka sama, jeśli do funkcji trzeba przekazać parametry: onclick="funkcja(val1, val2,...)" W naszym przykładzie kliknięcie przycisku Effacer wywołuje następującą funkcję JavaScript effacer: Funkcja effacer wyświetla komunikat: ![]() |
2.8.1.10. Przycisk typu „submit”
<input type="submit" value="Wyślij" name="cmdRenvoyer"> |
![]()
<input type="submit" value="Wyślij" name="cmdRenvoyer"> | |
type="submit": określa przycisk jako przycisk wysyłający dane formularza do serwera internetowego. Gdy użytkownik kliknie ten przycisk, przeglądarka wyśle dane formularza do adresu URL określonego w atrybucie action tagu <form> zgodnie z metodą określoną przez atrybut method tego samego tagu. value="Wyślij": tekst wyświetlany na przycisku |
2.8.1.11. Przycisk typu reset
<input type="reset" value="Przywróć" name="cmdRétablir"> |
![]()
<input type="reset" value="Przywróć" name="cmdRétablir"> | |
type="reset": określa przycisk jako przycisk resetowania formularza. Gdy użytkownik kliknie ten przycisk, przeglądarka przywróci formularz do stanu, w jakim go otrzymała. value="Przywróć" : tekst wyświetlany na przycisku |
2.8.1.12. Ukryte pole
<input type="hidden" name="secret" value="uneValeur"> |
<input type="hidden" name="..." value="..."> | |
type="hidden": określa, że jest to pole ukryte. Pole ukryte stanowi część formularza, ale nie jest widoczne dla użytkownika. Jeśli jednak użytkownik poprosiłby przeglądarkę o wyświetlenie kodu źródłowego, zobaczyłby tag <input type="hidden" value="..."> i tym samym wartość pola ukrytego. value="uneValeur": wartość pola ukrytego. Jaka jest rola pola ukrytego? Pozwala ono serwerowi internetowemu na zachowanie informacji w trakcie kolejnych żądań wysyłanych przez klienta. Rozważmy przykład aplikacji do zakupów internetowych. Klient kupuje pierwszy produkt o numerze art1 w ilości q1 na pierwszej stronie katalogu, a następnie przechodzi do kolejnej strony katalogu. Aby zapamiętać, że klient kupił q1 sztuk produktu art1, serwer może umieścić te dwie informacje w ukrytym polu formularza internetowego na nowej stronie. Na tej nowej stronie klient kupuje produkty o numerach q2 i art2. Gdy dane z tego drugiego formularza zostaną wysłane na serwer (submit), serwer otrzyma nie tylko informację (q2,art2), ale także (q1,art1), które również stanowią część formularza jako ukryte pola, których użytkownik nie może modyfikować. Serwer WWW umieści wówczas w nowym ukrytym polu informacje (q1,art1) oraz (q2,art2) i wyśle nową stronę katalogu. I tak dalej. |
2.8.2. Wysyłanie wartości formularza do serwera WWW przez klienta WWW
W poprzednim rozdziale wspomnieliśmy, że klient internetowy dysponuje dwiema metodami wysyłania do serwera internetowego wartości z wyświetlonego formularza: metodami GET i POST. Przyjrzyjmy się na przykładzie różnicy między tymi dwiema metodami. Wróćmy do poprzedniego przykładu i potraktujmy go w następujący sposób:
- przeglądarka wysyła żądanie dotyczące formularza z przykładu o numerze URL do serwera internetowego
- po otrzymaniu formularza wypełniamy go
- zanim wyślemy wartości formularza do serwera internetowego, klikając przycisk o typie submit o nazwie Envoyer, zatrzymujemy serwer internetowy i zastępujemy go generycznym serwerem TCP, z którego korzystaliśmy już wcześniej. Przypomnijmy, że serwer ten wyświetla na ekranie wiersze tekstu przesłane przez klienta internetowego. W ten sposób zobaczymy, co dokładnie wysyła przeglądarka.
Formularz wypełnia się w następujący sposób:

Kod URL użyty w tym dokumencie wygląda następująco:

2.8.2.1. Metoda GET
Dokument HTML jest zaprogramowany tak, aby przeglądarka wykorzystywała metodę GET do wysyłania wartości formularza na serwer WWW. Wpisaliśmy zatem:
Wyłączamy serwer WWW i uruchamiamy nasz ogólny serwer TCP na porcie 81:
E:\data\serge\JAVA\SOCKETS\serveur générique>java serveurTCPgenerique 81
Serveur générique lancé sur le port 81
Teraz wracamy do przeglądarki, aby wysłać dane z formularza do serwera WWW za pomocą przycisku Envoyer:

Oto, co otrzymuje serwer generyczny TCP:
<-- GET /html/balises.htm?R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&area
Saisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&
cmdRenvoyer=Envoyer&secret=uneValeur HTTP/1.1
<-- Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd
.ms-powerpoint, application/vnd.ms-excel, */*
<-- Referer: http://localhost:81/html/balises.htm
<-- Accept-Language: fr
<-- Accept-Encoding: gzip, deflate
<-- User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)
<-- Host: localhost:81
<-- Connection: Keep-Alive
<--
Wszystko znajduje się w pierwszym nagłówku HTTP wysłanym przez przeglądarkę:
<-- GET /html/balises.htm?R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&area
Saisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&
cmdRenvoyer=Envoyer&secret=uneValeur HTTP/1.1
Widać, że jest on znacznie bardziej złożony niż te, z którymi mieliśmy do czynienia do tej pory. Znajdujemy w nim składnię GET URL HTTP/1.1, ale w szczególnej postaci: GET URL?param1=wartość1¶m2=wartość2&... HTTP/1.1, gdzie parami to nazwy elementów kontrolnych formularza internetowego, a wartości to przypisane do nich wartości. Przyjrzyjmy się im bliżej. Poniżej przedstawiamy tabelę z trzema kolumnami:
- kolumna 1: zawiera definicję elementu sterującego HTML z przykładu
- kolumna 2: przedstawia wygląd tego elementu w przeglądarce
- kolumna 3: przedstawia wartość wysyłaną do serwera przez przeglądarkę dla elementu z kolumny 1 w postaci, jaką ma ona w zapytaniu GET z przykładu
element sterujący HTML | wygląd | zwracana(-e) wartość(-i) |
<input type="radio" value="Tak" name="R1">Tak <input type="radio" name="R1" value="nie" checked>Nie | – wartość atrybutu value przycisku opcji zaznaczonego przez użytkownika. | |
<input type="checkbox" name="C1" value="jeden">1 <input type="checkbox" name="C2" value="dwa" checked>2 <input type="checkbox" name="C3" value="trzy">3 | C1=jeden C2=dwa – wartości atrybutów value pól zaznaczonych przez użytkownika | |
<input type="text" name="txtSaisie" size="20" value="kilka słów"> | txtSaisie=programowanie+web - tekst wpisany przez użytkownika w polu wprowadzania danych. Spacje zostały zastąpione znakiem + | |
<input type="password" name="txtMdp" size="20" value="unMotDePasse"> | txtMdp=tojesttajemnica - tekst wpisany przez użytkownika w polu wprowadzania danych | |
<textarea rows="2" name="areaSaisie" cols="20"> wiersz1 wiersz 2 wiersz 3 </textarea> | areaSaisie=podstawy+programowania+%0D%0A programowania+stron+internetowych – tekst wpisany przez użytkownika w polu wprowadzania danych. %OD%OA to znacznik końca linii. Spacje zostały zastąpione znakiem + | |
<select size="1" name="cmbValeurs"> <option>opcja1</option> <option selected>opcja2</option> <option>opcja3</option> </select> | cmbValeurs=opcja3 – wartość wybrana przez użytkownika z listy z jednym wyborem | |
<select size="3" name="lst1"> <option selected>lista1</option> <option>lista2</option> <option>lista3</option> <option>lista4</option> <option>lista5</option> </select> | ![]() | lst1=lista3 - wartość wybrana przez użytkownika z listy z jednym wyborem |
<select size="3" name="lst2" multiple> <option selected>lista1</option> <option>lista2</option> <option selected>lista3</option> <option>lista4</option> <option>lista5</option> </select> | ![]() | lst2=lista1 lst2=lista3 - wartości wybrane przez użytkownika z listy wielokrotnego wyboru |
<input type="submit" value="Wyślij" name="cmdRenvoyer"> | cmdRenvoyer=Wyślij - nazwa i atrybut value przycisku, który posłużył do wysłania danych formularza na serwer | |
<input type="hidden" name="secret" value="uneValeur"> | secret=jakaswartość - atrybut value pola ukrytego |
Powtórzmy tę samą czynność, ale tym razem pozostawiając serwerowi WWW zadanie wygenerowania odpowiedzi i zobaczmy, jaka ona będzie. Strona zwrócona przez serwer WWW wygląda następująco:

Jest to dokładnie ta sama strona, którą otrzymaliśmy początkowo, przed wypełnieniem formularza. Aby zrozumieć dlaczego, należy ponownie przyjrzeć się kodu URL, o który prosi przeglądarka, gdy użytkownik naciska przycisk Envoyer:
<-- GET /html/balises.htm?R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&area
Saisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&
cmdRenvoyer=Envoyer&secret=uneValeur HTTP/1.1
Żądana strona to /html/balises.htm. Ponadto do tej strony przekazywane są wartości z formularza. Na razie strona URL /html/balises.htm, która jest stroną statyczną, nie wykorzystuje tych wartości. W związku z tym poprzedni kod GET jest równoważny z
i właśnie dlatego serwer ponownie zwrócił nam stronę początkową. Należy zauważyć, że przeglądarka wyświetla prawidłowo pełną stronę URL, o którą prosiliśmy:

2.8.2.2. Metoda POST
Dokument HTML jest zaprogramowany tak, aby przeglądarka korzystała teraz z metody POST w celu wysłania wartości formularza do serwera WWW:
Wyłączamy serwer WWW i uruchamiamy ogólny serwer TCP (już znany, ale nieco zmodyfikowany na tę okazję) na porcie 81:
E:\data\serge\JAVA\SOCKETS\serveur générique>java serveurTCPgenerique2 81
Serveur générique lancé sur le port 81
Teraz wracamy do przeglądarki, aby wysłać dane z formularza do serwera WWW za pomocą przycisku „Wyślij”:

Oto, co otrzymuje serwer generyczny TCP:
<-- POST /html/balises.htm HTTP/1.1
<-- Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/vnd
.ms-powerpoint, application/vnd.ms-excel, */*
<-- Referer: http://localhost:81/html/balises.htm
<-- Accept-Language: fr
<-- Content-Type: application/x-www-form-urlencoded
<-- Accept-Encoding: gzip, deflate
<-- User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705)
<-- Host: localhost:81
<-- Content-Length: 210
<-- Connection: Keep-Alive
<-- Cache-Control: no-cache
<--
<-- R1=Oui&C1=un&C2=deux&txtSaisie=programmation+web&txtMdp=ceciestsecret&areaSaisie=les+bases+de+la%0D%0Aprogrammation+web&cmbValeurs=choix3&lst1=liste3&lst2=liste1&lst2=liste3&cmdRenvoyer=Envoyer&secret=uneValeur
W porównaniu z tym, co już znamy, zauważamy następujące zmiany w zapytaniu przeglądarki:
- Pierwotny nagłówek HTTP nie brzmi już GET, lecz POST. Składnia to POST URL HTTP/1.1, gdzie URL to wartość żądana przez przeglądarkę. Jednocześnie POST oznacza, że przeglądarka ma dane do przesłania na serwer.
- Wiersz Content-Type: application/x-www-form-urlencoded wskazuje, jaki typ danych wyśle przeglądarka. Są to dane formularza (x-www-form) zakodowane (urlencoded). Kodowanie to powoduje, że niektóre znaki przesyłanych danych są przekształcane, aby uniknąć błędów interpretacji po stronie serwera. W ten sposób spacja jest zastępowana znakiem +, a znak końca linii – %OD%OA,... Ogólnie rzecz biorąc, wszystkie znaki zawarte w danych, które mogą zostać błędnie zinterpretowane przez serwer (&, +, %, ...), są przekształcane na %XX, gdzie XX to ich kod szesnastkowy.
- Wiersz Content-Length: 210 informuje serwer, ile znaków klient wyśle mu po zakończeniu nagłówków HTTP, c.a.d, po pustym wierszu sygnalizującym koniec nagłówków.
- Dane (210 znaków): R1=Tak&C1=jeden&C2=dwa&txtSaisie=programowanie+stron+internetowych&txtMdp=tojesttajemnica&areaSaisie=podstawy+programowania+webowego%0D%0Aprogramowanie+webowe&cmbValeurs=wybór3&lst1=lista3&lst2=lista1&lst2=lista3&cmdRenvoyer=Wyślij&secret=uneValeur
Zauważamy, że dane przesyłane przez POST mają ten sam format, co dane przesyłane przez GET.
Czy jedna z tych metod jest lepsza od drugiej? Widzieliśmy, że jeśli wartości z formularza były wysyłane przez przeglądarkę metodą GET, przeglądarka wyświetlała w polu Adresse żądany parametr URL w postaci URL?param1=val1¶m2=val2&.... Można to postrzegać jako zaletę lub wadę:
- zaletą, jeśli chcemy umożliwić użytkownikowi dodanie tego skonfigurowanego adresu URL do ulubionych
- wadą, jeśli nie chcemy, aby użytkownik miał dostęp do niektórych informacji zawartych w formularzu, takich jak na przykład pola ukryte
W dalszej części będziemy stosować w naszych formularzach niemal wyłącznie metodę POST.
2.8.2.3. Pobieranie wartości z formularza internetowego
Strona statyczna wywołana przez klienta, który dodatkowo przesyła parametry za pomocą POST lub GET, nie jest w żaden sposób w stanie ich pobrać. Tylko program może to zrobić i to on zajmie się następnie wygenerowaniem odpowiedzi dla klienta – odpowiedzi, która będzie dynamiczna i zazwyczaj zależna od otrzymanych parametrów. Jest to dziedzina programowania internetowego, którą omówimy bardziej szczegółowo w następnym rozdziale wraz z prezentacją technologii programowania internetowego w Javie: serwletów i stron JSP.









