8. Anhänge
8.1. Webentwicklungs-Tools
Hier zeigen wir auf, wo die für die Webentwicklung erforderlichen Werkzeuge zu finden sind und wie sie installiert werden. Bei einigen Werkzeugen haben sich die Versionen weiterentwickelt, und es ist möglich, dass die hier gegebenen Erläuterungen für die neuesten Versionen nicht mehr zutreffen. Der Leser muss sich dann entsprechend anpassen... Im Kurs zur Webprogrammierung werden wir in erster Linie die folgenden Werkzeuge verwenden, die alle kostenlos verfügbar sind:
- einen aktuellen Browser, der XML anzeigen kann. Die Beispiele im Kurs wurden mit Internet Explorer 6 getestet.
- Ein aktuelles JDK (Java Development Kit). Die Beispiele in diesem Kurs wurden mit JDK 1.4 getestet. Dieses JDK enthält das Java 1.4-Browser-Plugin, mit dem Browser Java-Applets unter Verwendung von JDK 1.4 anzeigen können.
- Eine Java-Entwicklungsumgebung zum Schreiben von Java-Servlets. Hier ist es JBuilder 7.
- Webserver: Apache, PWS (Personal Web Server), Tomcat.
- Apache wird für die Entwicklung von Webanwendungen in PERL (Practical Extracting and Reporting Language) oder PHP (Personal Home Page) verwendet.
- PWS wird für die Entwicklung von Webanwendungen in ASP (Active Server Pages) oder PHP verwendet.
- Tomcat wird für die Entwicklung von Webanwendungen mit Java-Servlets oder JSP (Java Server Pages) verwendet
- Eine Datenbankverwaltungsanwendung: MySQL
- EasyPHP: ein Tool, das den Apache-Webserver, die Sprache PHP und das DBMS MySQL bündelt
8.1.1. Webserver, Browser, Skriptsprachen
- Wichtige Webserver
- Apache (Linux, Windows)
- Internet Information Server (IIS) (NT), Personal Web Server (PWS) (Windows 9x)
- Wichtige Browser
- Internet Explorer (Windows)
- Netscape (Linux, Windows)
- Serverseitige Skriptsprachen
- VBScript (IIS, PWS)
- JavaScript (IIS, PWS)
- Perl (Apache, IIS, PWS)
- PHP (Apache, IIS, PWS)
- Java (Apache, Tomcat)
- .NET-Sprachen
- Clientseitige Skriptsprachen
- VBScript (IE)
- JavaScript (IE, Netscape)
- PerlScript (IE)
- Java (IE, Netscape)
8.1.2. Wo Sie die Tools finden
http://www.netscape.com/ (Download-Link) | |
http://www.microsoft.com/windows/ie/default.asp | |
http://www.php.net http://www.php.net/downloads.php (Windows-Binärdateien) | |
http://www.activestate.com http://www.activestate.com/Products/ http://www.activestate.com/Products/ActivePerl/ | |
http://msdn.microsoft.com/scripting (folgen Sie dem Link zu Windows Script) | |
http://java.sun.com/ http://java.sun.com/downloads.html (JSE) http://java.sun.com/j2se/1.4/download.html | |
http://www.apache.org/ http://www.apache.org/dist/httpd/binaries/win32/ | |
im NT 4.0 Option Pack für Windows 95 enthalten auf der Windows 98-CD enthalten http://www.microsoft.com/ntserver/nts/downloads/recommended/NT4OptPk/win95.asp | |
http://www.microsoft.com | |
http://jakarta.apache.org/tomcat/ | |
http://www.borland.com/jbuilder/ http://www.borland.com/products/downloads/download_jbuilder.html | |
http://www.easyphp.org/ http://www.easyphp.org/telechargements.php3 |
8.1.3. EasyPHP
Diese Anwendung ist sehr praktisch, da sie Folgendes in einem einzigen Paket enthält:
- den Apache-Webserver (1.3.x)
- die Programmiersprache PHP (4.x)
- das MySQL-DBMS (3.23.x)
- ein MySQL-Verwaltungstool: PhpMyAdmin
Die Installationsanwendung sieht wie folgt aus:

Die Installation von EasyPHP ist unkompliziert, und es wird eine Verzeichnisstruktur im Dateisystem erstellt:

die ausführbare Datei der Anwendung | |
die Verzeichnisstruktur des Apache-Servers | |
das MySQL-Datenbankverzeichnis | |
die Verzeichnisstruktur der phpMyAdmin-Anwendung | |
die Verzeichnisstruktur von PHP | |
Stammverzeichnis des Verzeichnisbaums für Webseiten, die vom EasyPHP-Apache-Server bereitgestellt werden | |
Verzeichnis, in dem Sie CGI-Skripte für den Apache-Server ablegen können |
Der Hauptvorteil von EasyPHP besteht darin, dass die Anwendung vorkonfiguriert ist. Somit sind Apache, PHP und MySQL bereits für die Zusammenarbeit konfiguriert. Wenn Sie EasyPHP über die Verknüpfung im Menü „Programme“ starten, erscheint ein Symbol in der unteren rechten Ecke des Bildschirms.
![]() |
Es handelt sich um den Buchstaben E mit einem roten Punkt, der blinken sollte, wenn der Apache-Webserver und die MySQL-Datenbank in Betrieb sind. Wenn Sie mit der rechten Maustaste darauf klicken, gelangen Sie zu den Menüoptionen:

Über die Option „Administration“ können Sie Einstellungen konfigurieren und Funktionstests durchführen:

8.1.3.1. PHP-Verwaltung
Über die Schaltfläche „PHP-Info“ sollten Sie überprüfen können, ob die Kombination aus Apache und PHP ordnungsgemäß funktioniert: Es sollte eine Seite mit PHP-Informationen angezeigt werden:

Über die Schaltfläche „Erweiterungen“ wird eine Liste der installierten PHP-Erweiterungen angezeigt. Dabei handelt es sich eigentlich um Funktionsbibliotheken.

Der obige Bildschirm zeigt beispielsweise, dass die für die Nutzung der MySQL-Datenbank erforderlichen Funktionen vorhanden sind.
Über die Schaltfläche „Einstellungen“ werden der Benutzername und das Passwort des MySQL-Datenbankadministrators angezeigt.

Die Verwendung der MySQL-Datenbank würde den Rahmen dieser kurzen Übersicht sprengen, aber es ist hier klar, dass ein Passwort für den Datenbankadministrator festgelegt werden sollte.
8.1.3.2. Apache-Verwaltung
Ebenfalls auf der EasyPHP-Verwaltungsseite können Sie über den Link „Ihre Aliase“ Aliase definieren, die einem Verzeichnis zugeordnet sind. Auf diese Weise können Sie Webseiten außerhalb des www-Verzeichnisses in der EasyPHP-Verzeichnisstruktur ablegen.

Wenn Sie auf der oben genannten Seite die folgenden Informationen eingeben:

und auf die Schaltfläche „Validieren“ klicken, werden die folgenden Zeilen zur Datei <easyphp>\apache\conf\httpd.conf hinzugefügt:
Alias /st/ "e:/data/serge/web/"
<Directory "e:/data/serge/web">
Options FollowSymLinks Indexes
AllowOverride None
Order deny,allow
allow from 127.0.0.1
deny from all
</Directory>
<easyphp> bezieht sich auf das EasyPHP-Installationsverzeichnis. httpd.conf ist die Konfigurationsdatei des Apache-Servers. Sie können daher dasselbe Ergebnis erzielen, indem Sie diese Datei direkt bearbeiten. Änderungen an der Datei httpd.conf werden normalerweise sofort von Apache übernommen. Ist dies nicht der Fall, müssen Sie den Server über das EasyPHP-Symbol anhalten und neu starten:

Um unser Beispiel abzuschließen, können wir nun Webseiten im Verzeichnisbaum e:\data\serge\web ablegen:
und rufen Sie diese Seite unter dem Alias st auf:

In diesem Beispiel wurde der Apache-Server so konfiguriert, dass er auf Port 81 läuft. Sein Standardport ist 80. Dies wird durch die folgende Zeile in der Datei httpd.conf gesteuert, die wir bereits gesehen haben:
8.1.3.3. Die Apache-Konfigurationsdatei htpd.conf
Wenn Sie Apache feinabstimmen möchten, müssen Sie die Konfigurationsdatei httpd.conf manuell bearbeiten, die sich hier im Ordner <easyphp>\apache\conf befindet:

Hier sind einige wichtige Punkte, die Sie in dieser Konfigurationsdatei beachten sollten:
Rolle | |
gibt den Ordner an, der den Apache-Verzeichnisbaum enthält | |
gibt an, welchen Port der Webserver verwenden soll. In der Regel ist dies 80. Durch Ändern dieser Zeile können Sie den Webserver auf einem anderen Port laufen lassen | |
die E-Mail-Adresse des Apache-Serveradministrators | |
der Name des Rechners, auf dem der Apache-Server läuft | |
das Installationsverzeichnis des Apache-Servers. Wenn relative Dateinamen in der Konfigurationsdatei vorkommen, beziehen sie sich auf dieses Verzeichnis. | |
das Stammverzeichnis der vom Server bereitgestellten Webseiten. Hier entspricht die URL http://machine/rep1/fic1.html der Datei E:\Program Files\EasyPHP\www\rep1\fic1.html | |
legt die Eigenschaften des vorherigen Ordners fest | |
logs-Ordner, also effektiv <ServerRoot>\logs\error.log: E:\Program Files\EasyPHP\apache\logs\error.log. Dies ist die Datei, die Sie überprüfen sollten, wenn Sie feststellen, dass der Apache-Server nicht funktioniert. | |
E:\Program Files\EasyPHP\cgi-bin ist das Stammverzeichnis des Verzeichnisbaums, in dem Sie CGI-Skripte ablegen können. Somit ist die URL http://machine/cgi-bin/rep1/script1.pl die URL für das CGI-Skript E:\Program Files\EasyPHP\cgi-bin\rep1\script1.pl. | |
legt die Eigenschaften des oben genannten Ordners fest | |
Zeilen zum Laden von Modulen, die es Apache ermöglichen, mit PHP4 zu arbeiten. | |
legt die Dateiendungen fest, die als PHP-Dateien behandelt werden sollen |
8.1.3.4. MySQL-Verwaltung mit PhpMyAdmin
Klicken Sie auf der EasyPHP-Verwaltungsseite auf die Schaltfläche „PhpMyAdmin“:

Über die Dropdown-Liste unter „Home“ können Sie die . | ![]() |
Die Zahl in Klammern gibt die Anzahl der Tabellen an. Wenn Sie eine Datenbank auswählen, werden deren Tabellen angezeigt: | ![]() |
Die Webseite bietet eine Reihe von Operationen für die Datenbank an:

Wenn Sie auf den Link „Benutzer anzeigen“ klicken:

Hier gibt es nur einen Benutzer: root, der der MySQL-Administrator ist. Über den Link „Bearbeiten“ können Sie dessen Passwort ändern, das derzeit leer ist – eine Vorgehensweise, die für einen Administrator nicht empfohlen wird.
Wir werden nicht weiter auf phpMyAdmin eingehen, da es sich um ein funktionsreiches Programm handelt, das eine mehrere Seiten umfassende Erörterung verdienen würde.
8.1.4. PHP
Wir haben gesehen, wie man PHP über die EasyPHP-Anwendung erhält. Um PHP direkt zu beziehen, rufen Sie die Website http://www.php.net auf.
PHP ist nicht auf die Nutzung im Web beschränkt. Sie können es als Skriptsprache unter Windows verwenden. Erstellen Sie das folgende Skript und speichern Sie es als date.php:
<?
// script php affichant l'heure
$maintenant=date("j/m/y, H:i:s",time());
echo "Nous sommes le $maintenant";
?>
Wechseln Sie in einem DOS-Fenster in das Verzeichnis, in dem sich die Datei „date.php“ befindet, und führen Sie sie aus:
E:\data\serge\php\essais>"e:\program files\easyphp\php\php.exe" date.php
X-Powered-By: PHP/4.2.0
Content-type: text/html
Nous sommes le 18/07/02, 09:31:01
8.1.5. PERL
Am besten ist es, wenn Internet Explorer bereits installiert ist. Ist dies der Fall, konfiguriert Active Perl den Browser so, dass er PERL-Skripte in HTML-Seiten akzeptiert – Skripte, die vom IE selbst auf der Client-Seite ausgeführt werden. Die Active-Perl-Website finden Sie unter der URL http://www.activestate.comA. Bei der Installation wird PERL in einem Verzeichnis installiert, das wir <perl> nennen. Es enthält die folgende Verzeichnisstruktur:
DEISL1 ISU 32 403 23/06/00 17:16 DeIsL1.isu
BIN <REP> 23/06/00 17:15 bin
LIB <REP> 23/06/00 17:15 lib
HTML <REP> 23/06/00 17:15 html
EG <REP> 23/06/00 17:15 eg
SITE <REP> 23/06/00 17:15 site
HTMLHELP <REP> 28/06/00 18:37 htmlhelp
Die ausführbare Datei perl.exe befindet sich in <perl>\bin. Perl ist eine Skriptsprache, die unter Windows und Unix läuft. Sie wird auch in der Webprogrammierung verwendet. Schreiben wir unser erstes Skript:
# script PERL affichant l'heure
# modules
use strict;
# programme
my ($secondes,$minutes,$heure)=localtime(time);
print "Il est $heure:$minutes:$secondes\n";
Speichern Sie dieses Skript in einer Datei namens heure.pl. Öffnen Sie ein DOS-Fenster, wechseln Sie in das Verzeichnis, in dem sich das Skript befindet, und führen Sie es aus:
8.1.6. VBScript, JavaScript, PerlScript
Dies sind Skriptsprachen für Windows. Sie können in verschiedenen Umgebungen ausgeführt werden, wie zum Beispiel
- Windows Scripting Host zur direkten Verwendung in Windows, insbesondere zum Schreiben von Skripten für die Systemadministration
- Internet Explorer. Dort wird es in HTML-Seiten verwendet, denen es eine Interaktivität verleiht, die mit HTML allein nicht erreicht werden kann.
- Internet Information Server (IIS), Microsofts Webserver unter NT/2000, und dessen Äquivalent, Personal Web Server (PWS), unter Win9x. In diesem Fall wird VBScript für die serverseitige Webprogrammierung verwendet, eine von Microsoft als ASP (Active Server Pages) bezeichnete Technologie.
Laden Sie die Installationsdatei von der URL http://msdn.microsoft.com/scripting herunter und folgen Sie den Links zu Windows Script. Folgende Komponenten werden installiert:
- der Windows Scripting Host-Container, der verschiedene Skriptsprachen wie VBScript und JavaScript sowie andere wie PerlScript unterstützt, das in Active Perl enthalten ist.
- einen VBScript-Interpreter
- ein JavaScript-Interpreter
Führen wir ein paar kurze Tests durch. Erstellen wir das folgende VBScript-Programm:
' a class
class personne
Dim nom
Dim age
End class
' creation of a person object
Set p1=new personne
With p1
.nom="dupont"
.age=18
End With
' display properties person p1
With p1
wscript.echo "nom=" & .nom
wscript.echo "age=" & .age
End With
Dieses Programm verwendet Objekte. Nennen wir es „objects.vbs“ (die Erweiterung .vbs kennzeichnet eine VBScript-Datei). Wechseln Sie in das Verzeichnis, in dem sich die Datei befindet, und führen Sie sie aus:
E:\data\serge\windowsScripting\vbscript\poly\objets>cscript objets.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
nom=dupont
age=18
Erstellen wir nun das folgende JavaScript-Programm, das Arrays verwendet:
// tableau dans un variant
// tableau vide
tableau=new Array();
affiche(tableau);
// tableau croît dynamiquement
for(i=0;i<3;i++){
tableau.push(i*10);
}
// affichage tableau
affiche(tableau);
// encore
for(i=3;i<6;i++){
tableau.push(i*10);
}
affiche(tableau);
// tableaux à plusieurs dimensions
WScript.echo("-----------------------------");
tableau2=new Array();
for(i=0;i<3;i++){
tableau2.push(new Array());
for(j=0;j<4;j++){
tableau2[i].push(i*10+j);
}//for j
}// for i
affiche2(tableau2);
// fin
WScript.quit(0);
// ---------------------------------------------------------
function affiche(tableau){
// affichage tableau
for(i=0;i<tableau.length;i++){
WScript.echo("tableau[" + i + "]=" + tableau[i]);
}//for
}//function
// ---------------------------------------------------------
function affiche2(tableau){
// affichage tableau
for(i=0;i<tableau.length;i++){
for(j=0;j<tableau[i].length;j++){
WScript.echo("tableau[" + i + "," + j + "]=" + tableau[i][j]);
}// for j
}//for i
}//function
Dieses Programm verwendet Arrays. Nennen wir es arrays.js (die Endung .js kennzeichnet eine JavaScript-Datei). Wechseln Sie in das Verzeichnis, in dem es sich befindet, und führen Sie es aus:
E:\data\serge\windowsScripting\javascript\poly\tableaux>cscript tableaux.js
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. Tous droits réservés.
tableau[0]=0
tableau[1]=10
tableau[2]=20
tableau[0]=0
tableau[1]=10
tableau[2]=20
tableau[3]=30
tableau[4]=40
tableau[5]=50
-----------------------------
tableau[0,0]=0
tableau[0,1]=1
tableau[0,2]=2
tableau[0,3]=3
tableau[1,0]=10
tableau[1,1]=11
tableau[1,2]=12
tableau[1,3]=13
tableau[2,0]=20
tableau[2,1]=21
tableau[2,2]=22
tableau[2,3]=23
Zum Abschluss noch ein letztes Beispiel in PerlScript. Um auf PerlScript zugreifen zu können, muss Active Perl installiert sein.
<job id="PERL1">
<script language="PerlScript">
# du Perl classique
%dico=("maurice"=>"juliette","philippe"=>"marianne");
@cles= keys %dico;
for ($i=0;$i<=$#cles;$i++){
$cle=$cles[$i];
$valeur=$dico{$cle};
$WScript->echo ("clé=".$cle.", valeur=".$valeur);
}
# du perlscript utilisant les objets Windows Script
$dico=$WScript->CreateObject("Scripting.Dictionary");
$dico->add("maurice","juliette");
$dico->add("philippe","marianne");
$WScript->echo($dico->item("maurice"));
$WScript->echo($dico->item("philippe"));
</script>
</job>
Dieses Programm demonstriert die Erstellung und Verwendung von zwei Wörterbüchern: eines im klassischen Perl-Stil, das andere unter Verwendung des Windows Script Scripting Dictionary-Objekts. Speichern wir diesen Code in der Datei dico.wsf (wsf ist die Dateiendung für Windows Script-Dateien). Wechseln Sie in den Programmordner und führen Sie es aus:
E:\data\serge\windowsScripting\perlscript\essais>cscript dico.wsf
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. Tous droits réservés.
clé=philippe, valeur=marianne
clé=maurice, valeur=juliette
juliette
marianne
PerlScript kann Objekte aus dem Container verwenden, in dem es ausgeführt wird. In diesem Fall handelte es sich um Objekte aus dem Windows Script-Container. Im Kontext der Webprogrammierung können VBScript-, JavaScript- und PerlScript-Skripte entweder im IE-Browser oder auf einem PWS- oder IIS-Server ausgeführt werden. Wenn das Skript etwas komplex ist, kann es sinnvoll sein, es außerhalb des Webkontexts zu testen, und zwar im Windows Script-Container, wie zuvor gezeigt. Auf diese Weise können Sie nur die Funktionen des Skripts testen, die keine browser- oder serverspezifischen Objekte verwenden. Selbst mit dieser Einschränkung bleibt diese Option nützlich, da es im Allgemeinen ziemlich unpraktisch ist, Skripte zu debuggen, die auf Webservern oder in Browsern laufen.
8.1.7. JAVA
Java ist unter der URL http://www.sun.com verfügbar und wird in einer Verzeichnisstruktur namens <java> installiert, die folgende Elemente enthält:
22/05/2002 05:51 <DIR> .
22/05/2002 05:51 <DIR> ..
22/05/2002 05:51 <DIR> bin
22/05/2002 05:51 <DIR> jre
07/02/2002 12:52 8 277 README.txt
07/02/2002 12:52 13 853 LICENSE
07/02/2002 12:52 4 516 COPYRIGHT
07/02/2002 12:52 15 290 readme.html
22/05/2002 05:51 <DIR> lib
22/05/2002 05:51 <DIR> include
22/05/2002 05:51 <DIR> demo
07/02/2002 12:52 10 377 848 src.zip
11/02/2002 12:55 <DIR> docs
Im Verzeichnis „bin“ finden Sie „javac.exe“, den Java-Compiler, und „java.exe“, die Java Virtual Machine. Sie können die folgenden Tests durchführen:
- Schreiben Sie das folgende Skript:
//java program displaying the time
import java.io.*;
import java.util.*;
public class heure{
public static void main(String arg[]){
// retrieve date & time
Date maintenant=new Date();
// we display
System.out.println("Il est "+maintenant.getHours()+
":"+maintenant.getMinutes()+":"+maintenant.getSeconds());
}//hand
}//class
- Speichern Sie dieses Programm als heure.java. Öffnen Sie ein DOS-Fenster. Wechseln Sie in das Verzeichnis, das die Datei heure.java enthält, und kompilieren Sie sie:
D:\data\java\essais>c:\jdk1.3\bin\javac heure.java
Note: heure.java uses or overrides a deprecated API.
Note: Recompile with -deprecation for details.
Im obigen Befehl muss c:\jdk1.3\bin\javac durch den genauen Pfad zum Compiler javac.exe ersetzt werden. Sie sollten nun eine Datei namens heure.class im selben Verzeichnis wie heure.java haben; dies ist das Programm, das nun von der virtuellen Maschine java.exe ausgeführt wird.
- Führen Sie das Programm aus:
8.1.8. Apache-Server
Wir haben gesehen, dass der Apache-Server über die EasyPHP-Anwendung bezogen werden kann. Um ihn direkt herunterzuladen, rufen Sie die Apache-Website auf: http://www.apache.org. Bei der Installation wird eine Verzeichnisstruktur erstellt, die alle für den Server erforderlichen Dateien enthält. Nennen wir dieses Verzeichnis <apache>. Es enthält eine Verzeichnisstruktur, die in etwa wie folgt aussieht:
UNINST ISU 118 805 23/06/00 17:09 Uninst.isu
HTDOCS <REP> 23/06/00 17:09 htdocs
APACHE~1 DLL 299 008 25/02/00 21:11 ApacheCore.dll
ANNOUN~1 3 000 23/02/00 16:51 Announcement
ABOUT_~1 13 197 31/03/99 18:42 ABOUT_APACHE
APACHE EXE 20 480 25/02/00 21:04 Apache.exe
KEYS 36 437 20/08/99 11:57 KEYS
LICENSE 2 907 01/01/99 13:04 LICENSE
MAKEFI~1 TMP 27 370 11/01/00 13:47 Makefile.tmpl
README 2 109 01/04/98 6:59 README
README NT 3 223 19/03/99 9:55 README.NT
WARNIN~1 TXT 339 21/09/98 13:09 WARNING-NT.TXT
BIN <REP> 23/06/00 17:09 bin
MODULES <REP> 23/06/00 17:09 modules
ICONS <REP> 23/06/00 17:09 icons
LOGS <REP> 23/06/00 17:09 logs
CONF <REP> 23/06/00 17:09 conf
CGI-BIN <REP> 23/06/00 17:09 cgi-bin
PROXY <REP> 23/06/00 17:09 proxy
INSTALL LOG 3 779 23/06/00 17:09 install.log
Verzeichnis der Apache-Konfigurationsdateien | |
Verzeichnis der Apache-Protokolldateien (Überwachung) | |
Ausführbare Apache-Dateien |
8.1.8.1. Konfiguration
Im Verzeichnis <Apache>\conf finden Sie die folgenden Dateien: httpd.conf, srm.conf, access.conf. In den neuesten Versionen von Apache wurden diese drei Dateien in httpd.conf zusammengefasst. Wir haben bereits die wichtigsten Punkte dieser Konfigurationsdatei behandelt. In den folgenden Beispielen wurde die Apache-Version von EasyPHP zum Testen verwendet und somit auch deren Konfigurationsdatei. In dieser Datei ist DocumentRoot, das den Stamm des Verzeichnisbaums der Webseite angibt, e:\program files\easyphp\www.
8.1.8.2. PHP – Apache-Verbindung
Erstellen Sie zum Testen die Datei intro.php mit der folgenden einzigen Zeile:
<? phpinfo() ?>
und legen Sie sie im Stammverzeichnis der Webseiten des Apache-Servers ab (DocumentRoot oben). Rufen Sie die URL http://localhost/intro.php auf. Sie sollten eine Liste mit PHP-Informationen sehen:

Das folgende PHP-Skript zeigt die Uhrzeit an. Wir haben es bereits gesehen:
<?php
// time: number of milliseconds since 01/01/1970
// "date-time display format
// d: 2-digit day
// m: 2-digit month
// y: 2-digit year
// H: hour 0.23
// i : minutes
// s: seconds
print "Nous sommes le " . date("d/m/y H:i:s",time());
?>
Legen Sie diese Textdatei im Stammverzeichnis des Apache-Servers (DocumentRoot) ab und nennen Sie sie date.php. Öffnen Sie einen Browser und geben Sie die URL http://localhost/date.php ein. Sie sehen dann die folgende Seite:

8.1.8.3. PERL-APACHE-Verbindung
Dies wird durch eine Zeile der Form ScriptAlias /cgi-bin/ "E:/Program Files/EasyPHP/cgi-bin/" in der Datei <apache>\conf\httpd.conf erreicht. Die Syntax lautet ScriptAlias /cgi-bin/ "<cgi-bin>", wobei <cgi-bin> der Ordner ist, in dem CGI-Skripte abgelegt werden können. CGI (Common Gateway Interface) ist ein Standard für die Kommunikation zwischen dem Webserver und Anwendungen. Ein Client fordert eine dynamische Seite vom Webserver an, d. h. eine Seite, die von einem Programm generiert wird. Der Webserver muss daher ein Programm anweisen, die Seite zu generieren. CGI definiert die Interaktion zwischen dem Server und dem Programm, insbesondere wie Informationen zwischen diesen beiden Entitäten übertragen werden.
Ändern Sie gegebenenfalls die Zeile ScriptAlias /cgi-bin/ "<cgi-bin>" und starten Sie den Apache-Server neu. Führen Sie anschließend folgenden Test durch:
- Schreiben Sie das Skript:
#!c:\perl\bin\perl.exe
# script PERL affichant l'heure
# modules
use strict;
# programme
my ($secondes,$minutes,$heure)=localtime(time);
print <<FINHTML
Content-Type: text/html
<html>
<head>
<title>heure</title>
</head>
<body>
<h1>Il est $heure:$minutes:$secondes</h1>
</body>
FINHTML
;
- Speichern Sie dieses Skript unter <cgi-bin>\heure.pl, wobei <cgi-bin> das Verzeichnis ist, das CGI-Skripte empfangen kann (siehe httpd.conf). Die erste Zeile, #!c:\perl\bin\perl.exe, gibt den Pfad zur ausführbaren Datei perl.exe an. Ändern Sie diesen bei Bedarf.
- Starten Sie Apache, falls Sie dies noch nicht getan haben
- Rufen Sie die URL http://localhost/cgi-bin/heure.pl in einem Browser auf. Sie sehen die folgende Seite:

8.1.9. Der PWS-Server
8.1.9.1. Installation
Der PWS (Personal Web Server) ist eine persönliche Version von Microsofts IIS (Internet Information Server). IIS ist auf NT- und 2000-Rechnern verfügbar. Auf Win9x-Rechnern ist PWS normalerweise im Installationspaket des Internet Explorers enthalten. Es wird jedoch nicht standardmäßig installiert. Sie müssen eine benutzerdefinierte Installation des IE durchführen und die Installation von PWS anfordern. Es ist auch im NT 4.0 Option Pack für Windows 95 enthalten.
8.1.9.2. Erste Tests
Das Stammverzeichnis für PWS-Webseiten ist Laufwerk:\inetpub\wwwroot, wobei „Laufwerk“ das Laufwerk ist, auf dem Sie PWS installiert haben. Wir gehen im Folgenden davon aus, dass dieses Laufwerk D ist. Somit entspricht die URL http://machine/rep1/page1.html der Datei d:\inetpub\wwwroot\rep1\page1.html. Der PWS-Server interpretiert jede Datei mit der Erweiterung .asp (Active Server Pages) als Skript, das er ausführen muss, um eine HTML-Seite zu generieren.
PWS läuft standardmäßig auf Port 80. Der Apache-Webserver ebenfalls... Sie müssen daher Apache beenden, um mit PWS arbeiten zu können, wenn Sie beide Server haben. Die andere Lösung besteht darin, Apache so zu konfigurieren, dass er auf einem anderen Port läuft. Ersetzen Sie in der Apache-Konfigurationsdatei httpd.conf die Zeile Port 80</mark> durch Port 81</mark>. Apache läuft nun auf Port 81 und kann gleichzeitig mit PWS verwendet werden. Wenn PWS läuft und Sie die URL http://localhost aufrufen, sehen Sie eine Seite, die in etwa wie folgt aussieht:

8.1.9.3. PHP – PWS-Verbindung
- Unten finden Sie eine .reg-Datei zum Ändern der Registrierung. Doppelklicken Sie auf diese Datei, um die Registrierung zu ändern. Hier befindet sich die erforderliche DLL zusammen mit der ausführbaren PHP-Datei in d:\php4. Nehmen Sie die erforderlichen Änderungen vor. Die Backslashes (\) im DLL-Pfad müssen verdoppelt werden.
REGEDIT4
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map]
".php"="d:\\php4\\php4isapi.dll"
- Starten Sie den Computer neu, damit die Änderung in der Registrierung wirksam wird.
- Erstellen Sie einen Ordner „php“ in d:\inetpub\wwwroot, dem Stammverzeichnis des PWS-Servers. Öffnen Sie anschließend PWS und wechseln Sie zur Registerkarte „Erweitert“. Klicken Sie auf die Schaltfläche „Hinzufügen“, um ein virtuelles Verzeichnis zu erstellen:
- Bestätigen Sie die Einstellungen und starten Sie PWS neu. Legen Sie die Datei intro.php in d:\inetpub\wwwroot\php ab, die nur die folgende Zeile enthält:
- Rufen Sie die URL http://localhost/php/intro.php vom PWS-Server auf. Sie sollten nun die Liste der PHP-Informationen sehen, die bereits mit Apache angezeigt wurde.
8.1.10. Tomcat: Java-Servlets und JSP (Java Server Pages)
Tomcat ist ein Webserver, der HTML-Seiten mithilfe von Servlets (vom Webserver ausgeführte Java-Programme) oder JSP (Java Server Pages) generiert, die Java-Code mit HTML-Code kombinieren. Er entspricht ASP (Active Server Pages) auf dem IIS/PWS-Server von Microsoft, wo VBScript- oder JavaScript-Code mit HTML-Code kombiniert wird.
8.1.10.1. Installation
Tomcat ist unter der URL http://jakarta.apache.org verfügbar. Sie laden eine .exe-Installationsdatei herunter. Wenn Sie dieses Programm ausführen, werden Sie zunächst aufgefordert, das zu verwendende JDK auszuwählen. Dies liegt daran, dass Tomcat ein JDK benötigt, um sich selbst zu installieren und anschließend Java-Servlets zu kompilieren und auszuführen. Sie müssen daher vor der Installation von Tomcat ein Java-JDK installiert haben. Es wird das aktuellste JDK empfohlen. Die Installation erstellt eine <tomcat>-Verzeichnisstruktur:

Dies beinhaltet lediglich das Entpacken dieses Archivs in ein Verzeichnis. Wählen Sie ein Verzeichnis, dessen Pfad nur Namen ohne Leerzeichen enthält (also beispielsweise nicht „Programme“), da es einen Fehler im Tomcat-Installationsprozess gibt. Verwenden Sie beispielsweise C:\tomcat oder D:\tomcat. Nennen wir dieses Verzeichnis <tomcat>. Darin finden Sie einen Ordner namens jakarta-tomcat, und in diesem Ordner die folgende Verzeichnisstruktur:
LOGS <REP> 15/11/00 9:04 logs
LICENSE 2 876 18/04/00 15:56 LICENSE
CONF <REP> 15/11/00 8:53 conf
DOC <REP> 15/11/00 8:53 doc
LIB <REP> 15/11/00 8:53 lib
SRC <REP> 15/11/00 8:53 src
WEBAPPS <REP> 15/11/00 8:53 webapps
BIN <REP> 15/11/00 8:53 bin
WORK <REP> 15/11/00 9:04 work
8.1.10.2. Starten/Beenden des Tomcat-Webservers
Tomcat ist ein Webserver, genau wie Apache oder PWS. Um ihn zu starten, verwenden Sie die Links im Menü „Programme“:
um Tomcat zu starten | |
um es zu beenden |
Wenn Sie Tomcat starten, erscheint ein DOS-Fenster mit folgendem Inhalt:

Sie können dieses DOS-Fenster minimieren. Es bleibt geöffnet, solange Tomcat läuft. Anschließend können Sie mit den ersten Tests fortfahren. Der Tomcat-Webserver läuft auf Port 8080. Sobald Tomcat läuft, öffnen Sie einen Webbrowser und geben Sie die URL http://localhost:8080 ein. Sie sollten die folgende Seite sehen:

Folgen Sie dem Link „Servlet Examples“:

Klicken Sie auf den Link „Ausführen“ für „RequestParameters“ und anschließend auf den für „Source“. So erhalten Sie einen ersten Eindruck davon, was ein Java-Servlet ist. Das Gleiche können Sie mit den Links auf den JSP-Seiten tun.
Um Tomcat zu beenden, klicken Sie im Menü „Programme“ auf den Link „Tomcat beenden“.
8.1.11. JBuilder
JBuilder ist eine Entwicklungsumgebung für Java-Anwendungen. Um Java-Servlets ohne grafische Benutzeroberflächen zu erstellen, ist eine solche Umgebung nicht unbedingt erforderlich. Ein Texteditor und ein JDK reichen aus. JBuilder bietet jedoch gegenüber der vorherigen Methode einige Vorteile:
- Einfache Fehlersuche: Der Compiler markiert fehlerhafte Zeilen im Programm, und man gelangt leicht zu ihnen
- Code-Vervollständigung: Bei der Verwendung eines Java-Objekts zeigt JBuilder eine Liste seiner Eigenschaften und Methoden direkt im Code an. Dies ist sehr nützlich, da die meisten Java-Objekte zahlreiche Eigenschaften und Methoden haben, die schwer zu merken sind.
JBuilder ist unter http://www.borland.com/jbuilder zu finden. Um die Software zu erhalten, müssen Sie ein Formular ausfüllen. Ein Aktivierungsschlüssel wird per E-Mail versendet. Um beispielsweise JBuilder 7 zu installieren, wurden die folgenden Schritte durchgeführt:
- Es wurden drei ZIP-Dateien heruntergeladen: eine für die Anwendung, eine für die Dokumentation und eine für die Beispiele. Jede dieser ZIP-Dateien hat einen eigenen Link auf der JBuilder-Website.
- Zuerst wurde die Anwendung installiert, dann die Dokumentation und schließlich die Beispiele
- Wenn Sie die Anwendung zum ersten Mal starten, wird ein Aktivierungsschlüssel abgefragt: Dies ist der Schlüssel, der Ihnen per E-Mail zugesandt wurde. In Version 7 handelt es sich bei diesem Schlüssel tatsächlich um eine vollständige Textdatei, die beispielsweise im JB7-Installationsordner abgelegt werden kann. Wenn der Schlüssel abgefragt wird, geben Sie dann die betreffende Datei an. Sobald dies erledigt ist, wird der Schlüssel nicht mehr abgefragt.
Es gibt einige nützliche Konfigurationen, die Sie vornehmen sollten, wenn Sie JBuilder zum Erstellen von Java-Servlets verwenden möchten. Die sogenannte „Personal“-Version von JBuilder ist eine abgespeckte Version, die nicht alle für die Java-Webentwicklung erforderlichen Klassen enthält. Sie können JBuilder so konfigurieren, dass die von Tomcat bereitgestellten Klassenbibliotheken verwendet werden. So geht’s:
- Starten Sie JBuilder

- Aktivieren Sie die Option „Tools/Configure JDKs“

Im Abschnitt „JDK-Einstellungen“ oben wird im Feld „Name“ normalerweise „JDK 1.3.1“ angezeigt. Wenn Sie über ein neueres JDK verfügen, geben Sie über die Schaltfläche „Ändern“ dessen Installationsverzeichnis an. Im obigen Beispiel haben wir das Verzeichnis E:\Program Files\jdk14 angegeben, in dem ein JDK 1.4 installiert wurde. Von nun an verwendet JBuilder dieses JDK für seine Kompilierungen und Ausführungen. Im Abschnitt (Class, Source, Documentation) sehen Sie eine Liste aller Klassenbibliotheken, die JBuilder durchsucht – in diesem Fall die Klassen aus JDK 1.4. Die in diesem JDK enthaltenen Klassen reichen für die Java-Webentwicklung nicht aus. Um weitere Klassenbibliotheken hinzuzufügen, verwenden Sie die Schaltfläche „Add“ und geben Sie die zusätzlichen .jar-Dateien an, die Sie verwenden möchten. .jar-Dateien sind Klassenbibliotheken. Tomcat 4.x enthält alle für die Webentwicklung erforderlichen Klassenbibliotheken. Sie befinden sich unter <tomcat>\common\lib, wobei <tomcat> das Tomcat-Installationsverzeichnis ist:

Über die Schaltfläche „Hinzufügen“ fügen wir diese Bibliotheken nacheinander zur Liste der von JBuilder gescannten Bibliotheken hinzu:

Ab sofort können Sie Java-Programme kompilieren, die dem J2EE-Standard entsprechen, einschließlich Java-Servlets. JBuilder wird nur für die Kompilierung verwendet; die Ausführung erfolgt anschließend durch Tomcat gemäß den im Kurs erläuterten Verfahren.
8.2. Programmquellcode
8.2.1. Der generische TCP-Client
Viele Dienste, die in den Anfängen des Internets entstanden sind, funktionieren nach dem zuvor behandelten Echo-Server-Modell: Die Client-Server-Kommunikation erfolgt über den Austausch von Textzeilen. Wir werden einen generischen TCP-Client schreiben, der wie folgt gestartet wird: java cltTCPgenerique server port
Dieser TCP-Client stellt eine Verbindung zum Port port auf dem Server server her. Sobald die Verbindung hergestellt ist, erstellt er zwei Threads:
- einen Thread, der für das Einlesen der über die Tastatur eingegebenen Befehle und deren Weiterleitung an den Server zuständig ist
- einen Thread, der für das Lesen der Antworten des Servers und deren Anzeige auf dem Bildschirm zuständig ist
Warum zwei Threads? Jeder TCP-IP-Dienst hat sein eigenes spezifisches Protokoll, und es treten manchmal folgende Situationen auf:
- Der Client muss mehrere Zeilen Text senden, bevor er eine Antwort erhält
- Die Antwort eines Servers kann mehrere Zeilen Text enthalten
Daher ist die Schleife, die eine einzelne Zeile an den Server sendet und eine einzelne Zeile vom Server empfängt, nicht immer geeignet. Wir werden daher zwei separate Schleifen erstellen:
- eine Schleife zum Lesen der über die Tastatur eingegebenen Befehle, die an den Server gesendet werden sollen. Der Benutzer signalisiert das Ende der Befehle mit dem Schlüsselwort „fin“.
- eine Schleife zum Empfangen und Anzeigen der Antworten des Servers. Dies wird eine Endlosschleife sein, die nur unterbrochen wird, wenn der Server die Netzwerkverbindung schließt oder der Benutzer den Befehl „end“ über die Tastatur eingibt.
Um diese beiden separaten Schleifen zu haben, benötigen wir zwei unabhängige Threads. Schauen wir uns ein Ausführungsbeispiel an, bei dem unser generischer TCP-Client eine Verbindung zu einem SMTP-Dienst (Simple Mail Transfer Protocol) herstellt. Dieser Dienst ist für die Weiterleitung von E-Mails an ihre Empfänger zuständig. Er läuft auf Port 25 und verwendet ein textbasiertes Austauschprotokoll.
Dos>java clientTCPgenerique istia.univ-angers.fr 25
Commandes :
<-- 220 istia.univ-angers.fr ESMTP Sendmail 8.11.6/8.9.3; Mon, 13 May 2002 08:37:26 +0200
help
<-- 502 5.3.0 Sendmail 8.11.6 -- HELP not implemented
mail from: machin@univ-angers.fr
<-- 250 2.1.0 machin@univ-angers.fr... Sender ok
rcpt to: serge.tahe@istia.univ-angers.fr
<-- 250 2.1.5 serge.tahe@istia.univ-angers.fr... Recipient ok
data
<-- 354 Enter mail, end with "." on a line by itself
Subject: test
ligne1
ligne2
ligne3
.
<-- 250 2.0.0 g4D6bks25951 Message accepted for delivery
quit
<-- 221 2.0.0 istia.univ-angers.fr closing connection
[fin du thread de lecture des réponses du serveur]
fin
[fin du thread d'envoi des commandes au serveur]
Lassen Sie uns diese Client-Server-Kommunikation kommentieren:
- Der SMTP-Dienst sendet eine Willkommensnachricht, wenn ein Client eine Verbindung zu ihm herstellt:
- Einige Dienste verfügen über einen „help“-Befehl, der Informationen zu den für diesen Dienst verfügbaren Befehlen liefert. Das ist hier nicht der Fall. Die im Beispiel verwendeten SMTP-Befehle lauten wie folgt:
- mail from: Absender, um die E-Mail-Adresse des Absenders anzugeben
- rcpt to: Empfänger, um die E-Mail-Adresse des Empfängers der Nachricht anzugeben. Bei mehreren Empfängern wird der Befehl rcpt to: so oft wie nötig für jeden Empfänger wiederholt.
- data, das dem SMTP-Server signalisiert, dass die Nachricht versendet werden soll. Wie in der Antwort des Servers angegeben, handelt es sich hierbei um eine Folge von Zeilen, die mit einer Zeile endet, die nur einen Punkt enthält. Eine Nachricht kann Kopfzeilen enthalten, die durch eine Leerzeile vom Nachrichtentext getrennt sind. In unserem Beispiel haben wir einen Betreff mit dem Schlüsselwort Subject: eingefügt
- Sobald die Nachricht gesendet wurde, können wir dem Server mit dem Befehl „quit“ mitteilen, dass wir fertig sind. Der Server schließt daraufhin die Netzwerkverbindung. Der Lese-Thread kann dieses Ereignis erkennen und anhalten.
- Der Benutzer gibt dann „end“ über die Tastatur ein, um auch den Thread zu stoppen, der die über die Tastatur eingegebenen Befehle liest.
Wenn wir die empfangene E-Mail überprüfen, sehen wir Folgendes (Outlook):

Beachten Sie, dass der SMTP-Dienst nicht erkennen kann, ob ein Absender gültig ist oder nicht. Daher können Sie dem Feld „Von“ einer Nachricht niemals vertrauen. In diesem Fall existierte die Absender-E-Mail-Adresse machin@univ-angers.fr nicht.
Dieser generische TCP-Client ermöglicht es uns, das Kommunikationsprotokoll für Internetdienste zu untersuchen und darauf aufbauend spezialisierte Klassen für Clients dieser Dienste zu erstellen. Betrachten wir das Kommunikationsprotokoll für den POP-Dienst (Post Office Protocol), der es Benutzern ermöglicht, ihre auf einem Server gespeicherten E-Mails abzurufen. Er läuft auf Port 110.
Dos> java clientTCPgenerique istia.univ-angers.fr 110
Commandes :
<-- +OK Qpopper (version 4.0.3) at istia.univ-angers.fr starting.
help
<-- -ERR Unknown command: "help".
user st
<-- +OK Password required for st.
pass monpassword
<-- +OK st has 157 visible messages (0 hidden) in 11755927 octets.
list
<-- +OK 157 visible messages (11755927 octets)
<-- 1 892847
<-- 2 171661
...
<-- 156 2843
<-- 157 2796
<-- .
retr 157
<-- +OK 2796 octets
<-- Received: from lagaffe.univ-angers.fr (lagaffe.univ-angers.fr [193.49.144.1])
<-- by istia.univ-angers.fr (8.11.6/8.9.3) with ESMTP id g4D6wZs26600;
<-- Mon, 13 May 2002 08:58:35 +0200
<-- Received: from jaume ([193.49.146.242])
<-- by lagaffe.univ-angers.fr (8.11.1/8.11.2/GeO20000215) with SMTP id g4D6wSd37691;
<-- Mon, 13 May 2002 08:58:28 +0200 (CEST)
...
<-- ------------------------------------------------------------------------
<-- NOC-RENATER2 Tl. : 0800 77 47 95
<-- Fax : (+33) 01 40 78 64 00 , Email : noc-r2@cssi.renater.fr
<-- ------------------------------------------------------------------------
<--
<-- .
quit
<-- +OK Pop server at istia.univ-angers.fr signing off.
[fin du thread de lecture des réponses du serveur]
fin
[fin du thread d'envoi des commandes au serveur]
Die wichtigsten Befehle lauten wie folgt:
- user login, wobei Sie Ihren Benutzernamen auf dem Rechner eingeben, der Ihre E-Mails hostet
- pass password, wobei Sie das Passwort eingeben, das mit dem vorherigen Login verknüpft ist
- list, um eine Liste der Nachrichten im Format Nummer, Größe in Byte abzurufen
- retr i, um die Nachricht Nummer i zu lesen
- quit, um die Sitzung zu beenden.
Betrachten wir nun das Kommunikationsprotokoll zwischen einem Client und einem Webserver, der in der Regel auf Port 80 läuft:
Dos> java clientTCPgenerique istia.univ-angers.fr 80
Commandes :
GET /index.html HTTP/1.0
<-- HTTP/1.1 200 OK
<-- Date: Mon, 13 May 2002 07:30:58 GMT
<-- Server: Apache/1.3.12 (Unix) (Red Hat/Linux) PHP/3.0.15 mod_perl/1.21
<-- Last-Modified: Wed, 06 Feb 2002 09:00:58 GMT
<-- ETag: "23432-2bf3-3c60f0ca"
<-- Accept-Ranges: bytes
<-- Content-Length: 11251
<-- Connection: close
<-- Content-Type: text/html
<--
<-- <html>
<--
<-- <head>
<-- <meta http-equiv="Content-Type"
<-- content="text/html; charset=iso-8859-1">
<-- <meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<-- <title>Bienvenue a l'ISTIA - Universite d'Angers</title>
<-- </head>
....
<-- face="Verdana"> - Dernire mise jour le <b>10 janvier 2002</b></font></p>
<-- </body>
<-- </html>
<--
[fin du thread de lecture des réponses du serveur]
fin
[fin du thread d'envoi des commandes au serveur]
Ein Web-Client sendet seine Befehle nach folgendem Muster an den Server:
Der Webserver antwortet erst, nachdem er die Leerzeile empfangen hat. In diesem Beispiel haben wir nur einen Befehl verwendet:
der die URL /index.html vom Server anfordert und angibt, dass er HTTP Version 1.0 verwendet. Die aktuellste Version dieses Protokolls ist 1.1. Das Beispiel zeigt, dass der Server mit dem Inhalt der Datei index.html geantwortet und anschließend die Verbindung geschlossen hat, wie wir an der Meldung „thread terminating“ in der Antwort erkennen können. Vor dem Senden des Inhalts der Datei index.html hat der Webserver eine Reihe von Headern gesendet, gefolgt von einer Leerzeile:
<-- HTTP/1.1 200 OK
<-- Date: Mon, 13 May 2002 07:30:58 GMT
<-- Server: Apache/1.3.12 (Unix) (Red Hat/Linux) PHP/3.0.15 mod_perl/1.21
<-- Last-Modified: Wed, 06 Feb 2002 09:00:58 GMT
<-- ETag: "23432-2bf3-3c60f0ca"
<-- Accept-Ranges: bytes
<-- Content-Length: 11251
<-- Connection: close
<-- Content-Type: text/html
<--
<-- <html>
Die Zeile <html> ist die erste Zeile der Datei /index.html. Der vorangehende Text wird als HTTP-Header (HyperText Transfer Protocol) bezeichnet. Wir werden hier nicht näher auf diese Header eingehen, aber denken Sie daran, dass unser generischer Client Zugriff darauf bietet, was für das Verständnis hilfreich sein kann. Zum Beispiel die erste Zeile:
bedeutet, dass der kontaktierte Webserver das HTTP/1.1-Protokoll unterstützt und die angeforderte Datei erfolgreich gefunden hat (200 OK), wobei 200 ein HTTP-Antwortcode ist. Die Zeilen
Teilen Sie dem Client mit, dass er 11.251 Byte HTML-Text (HyperText Markup Language) erhalten wird und dass die Verbindung geschlossen wird, sobald die Daten gesendet wurden.
Hier haben wir also einen sehr praktischen TCP-Client. Er kann zwar weniger als das offizielle Telnet-Programm, aber es war interessant, ihn selbst zu schreiben. Das generische TCP-Client-Programm sieht wie folgt aus:
// imported packages
import java.io.*;
import java.net.*;
public class clientTCPgenerique{
// receives the characteristics of a service as a parameter in the form
// server port
// connects to the service
// creates a thread to read keyboard commands
// these will be sent to the
// creates a thread to read server responses
// these will be displayed on the screen
// the whole thing ends with the command end typed on the keyboard
// instance variable
private static Socket client;
public static void main(String[] args){
// syntax
final String syntaxe="pg serveur port";
// number of arguments
if(args.length != 2)
erreur(syntaxe,1);
// note the server name
String serveur=args[0];
// port must be integer >0
int port=0;
boolean erreurPort=false;
Exception E=null;
try{
port=Integer.parseInt(args[1]);
}catch(Exception e){
E=e;
erreurPort=true;
}
erreurPort=erreurPort || port <=0;
if(erreurPort)
erreur(syntaxe+"\n"+"Port incorrect ("+E+")",2);
client=null;
// there may be problems
try{
// connect to the service
client=new Socket(serveur,port);
}catch(Exception ex){
// error
erreur("Impossible de se connecter au service ("+ serveur
+","+port+"), erreur : "+ex.getMessage(),3);
// end
return;
}//catch
// create read/write threads
new ClientSend(client).start();
new ClientReceive(client).start();
// end thread main
return;
}// hand
// error display
public static void erreur(String msg, int exitCode){
// error display
System.err.println(msg);
// stop with error
System.exit(exitCode);
}//error
}//class
class ClientSend extends Thread {
// class for reading keyboard commands
// and send them to a server via a tcp client passed in parameter
private Socket client; // tcp client
// manufacturer
public ClientSend(Socket client){
// we note the tcp client
this.client=client;
}//manufacturer
// thread Run method
public void run(){
// local data
PrintWriter OUT=null; // network write streams
BufferedReader IN=null; // keyboard flow
String commande=null; // command read from keyboard
// error management
try{
// network write stream creation
OUT=new PrintWriter(client.getOutputStream(),true);
// keyboard input stream creation
IN=new BufferedReader(new InputStreamReader(System.in));
// order entry-send loop
System.out.println("Commandes : ");
while(true){
// read command typed on keyboard
commande=IN.readLine().trim();
// finished?
if (commande.toLowerCase().equals("fin")) break;
// send order to server
OUT.println(commande);
// next order
}//while
}catch(Exception ex){
// error
System.err.println("Envoi : L'erreur suivante s'est produite : " + ex.getMessage());
}//catch
// end - close flows
try{
OUT.close();client.close();
}catch(Exception ex){}
// signals the end of the thread
System.out.println("[Envoi : fin du thread d'envoi des commandes au serveur]");
}//run
}//class
class ClientReceive extends Thread{
// class responsible for reading lines of text intended for a
// tcp client passed as parameter
private Socket client; // tcp client
// manufacturer
public ClientReceive(Socket client){
// we note the tcp client
this.client=client;
}//manufacturer
// thread Run method
public void run(){
// local data
BufferedReader IN=null; // network read stream
String réponse=null; // server response
// error management
try{
// create network read stream
IN=new BufferedReader(new InputStreamReader(client.getInputStream()));
// loop read text lines from IN stream
while(true){
// network streaming
réponse=IN.readLine();
// closed flow?
if(réponse==null) break;
// display
System.out.println("<-- "+réponse);
}//while
}catch(Exception ex){
// error
System.err.println("Réception : L'erreur suivante s'est produite : " + ex.getMessage());
}//catch
// end - we close the feeds
try{
IN.close();client.close();
}catch(Exception ex){}
// signals the end of the thread
System.out.println("[Réception : fin du thread de lecture des réponses du serveur]");
}//run
}//class
8.2.2. Der generische TCP-Server
Nun sehen wir uns einen Server an
- , der die von seinen Clients gesendeten Befehle auf dem Bildschirm anzeigt
- und ihnen als Antwort die Textzeilen sendet, die ein Benutzer über die Tastatur eingegeben hat. Es ist also der Benutzer, der als Server fungiert.
Das Programm wird gestartet mit: java genericTCPserver listeningPort, wobei listeningPort der Port ist, mit dem sich die Clients verbinden müssen. Der Client-Dienst wird von zwei Threads abgewickelt:
- ein Thread, der ausschließlich für das Lesen der vom Client gesendeten Textzeilen zuständig ist
- ein Thread, der ausschließlich dem Lesen der vom Benutzer über die Tastatur eingegebenen Antworten gewidmet ist. Dieser Thread signalisiert mithilfe des Befehls `fin`, dass er die Verbindung zum Client schließt.
Der Server erstellt zwei Threads pro Client. Bei n Clients sind somit 2n Threads gleichzeitig aktiv. Der Server selbst wird nicht beendet, es sei denn, der Benutzer drückt die Tastenkombination Strg-C auf der Tastatur. Sehen wir uns einige Beispiele an.
Der Server läuft auf Port 100, und wir verwenden den generischen Client, um mit ihm zu kommunizieren. Das Client-Fenster sieht wie folgt aus:
E:\data\serge\MSNET\c#\réseau\client tcp générique> java clientTCPgenerique localhost 100
Commandes :
commande 1 du client 1
<-- réponse 1 au client 1
commande 2 du client 1
<-- réponse 2 au client 1
fin
L'erreur suivante s'est produite : Impossible de lire les données de la connexion de transport.
[fin du thread de lecture des réponses du serveur]
[fin du thread d'envoi des commandes au serveur]
Zeilen, die mit <-- beginnen, stammen vom Server und wurden an den Client gesendet; die anderen stammen vom Client und wurden an den Server gesendet. Das Serverfenster sieht wie folgt aus:
Dos> java serveurTCPgenerique 100
Serveur générique lancé sur le port 100
Thread de lecture des réponses du serveur au client 1 lancé
1 : Thread de lecture des demandes du client 1 lancé
<-- commande 1 du client 1
réponse 1 au client 1
1 : <-- commande 2 du client 1
réponse 2 au client 1
1 : [fin du Thread de lecture des demandes du client 1]
fin
[fin du Thread de lecture des réponses du serveur au client 1]
Zeilen, die mit <-- beginnen, sind vom Client an den Server gesendet. Zeilen N: sind vom Server an Client N gesendet. Der oben genannte Server ist weiterhin aktiv, obwohl Client 1 beendet ist. Wir starten einen zweiten Client für denselben Server:
Dos> java clientTCPgenerique localhost 100
Commandes :
commande 3 du client 2
<-- réponse 3 au client 2
fin
L'erreur suivante s'est produite : Impossible de lire les données de la connexion de transport.
[fin du thread de lecture des réponses du serveur]
[fin du thread d'envoi des commandes au serveur]
Das Serverfenster sieht dann wie folgt aus:
Dos> java serveurTCPgenerique 100
Serveur générique lancé sur le port 100
Thread de lecture des réponses du serveur au client 1 lancé
1 : Thread de lecture des demandes du client 1 lancé
<-- commande 1 du client 1
réponse 1 au client 1
1 : <-- commande 2 du client 1
réponse 2 au client 1
1 : [fin du Thread de lecture des demandes du client 1]
fin
[fin du Thread de lecture des réponses du serveur au client 1]
Thread de lecture des réponses du serveur au client 2 lancé
2 : Thread de lecture des demandes du client 2 lancé
<-- commande 3 du client 2
réponse 3 au client 2
2 : [fin du Thread de lecture des demandes du client 2]
fin
[fin du Thread de lecture des réponses du serveur au client 2]
^C
Simulieren wir nun einen Webserver, indem wir unseren generischen Server auf Port 88 ausführen:
Dos> java serveurTCPgenerique 88
Serveur générique lancé sur le port 88
Öffnen wir nun einen Browser und rufen die URL http://localhost:88/exemple.html auf. Der Browser stellt dann eine Verbindung zu Port 88 auf dem Localhost-Rechner her und fordert die Seite /example.html an:

Werfen wir nun einen Blick auf unser Serverfenster:
Dos>java serveurTCPgenerique 88
Serveur générique lancé sur le port 88
Thread de lecture des réponses du serveur au client 2 lancé
2 : Thread de lecture des demandes du client 2 lancé
<-- 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
<--
Dies zeigt die vom Browser gesendeten HTTP-Header. So können wir nach und nach mehr über das HTTP-Protokoll lernen. In einem früheren Beispiel haben wir einen Web-Client erstellt, der nur den GET-Befehl gesendet hat. Das war ausreichend. Hier sehen wir, dass der Browser weitere Informationen an den Server sendet. Diese Informationen sollen dem Server mitteilen, um welche Art von Client es sich handelt. Wir sehen auch, dass die HTTP-Header mit einer Leerzeile enden.
Erstellen wir eine Antwort für unseren Client. Der Benutzer am Bildschirm ist hier der eigentliche Server und kann manuell eine Antwort erstellen. Erinnern Sie sich an die Antwort, die ein Webserver in einem früheren Beispiel gesendet hat:
<-- HTTP/1.1 200 OK
<-- Date: Mon, 13 May 2002 07:30:58 GMT
<-- Server: Apache/1.3.12 (Unix) (Red Hat/Linux) PHP/3.0.15 mod_perl/1.21
<-- Last-Modified: Wed, 06 Feb 2002 09:00:58 GMT
<-- ETag: "23432-2bf3-3c60f0ca"
<-- Accept-Ranges: bytes
<-- Content-Length: 11251
<-- Connection: close
<-- Content-Type: text/html
<--
<-- <html>
Versuchen wir, eine ähnliche Antwort zu geben:
...
<-- Host: localhost:88
<-- Connection: Keep-Alive
<--
2 : HTTP/1.1 200 OK
2 : Server: serveur tcp generique
2 : Connection: close
2 : Content-Type: text/html
2 :
2 : <html>
2 : <head><title>Serveur generique</title></head>
2 : <body>
2 : <center>
2 : <h2>Reponse du serveur generique</h2>
2 : </center>
2 : </body>
2 : </html>
2 : fin
L'erreur suivante s'est produite : Impossible de lire les données de la connexion de transport.
[fin du Thread de lecture des demandes du client 2]
[fin du Thread de lecture des réponses du serveur au client 2]
Zeilen, die mit 2: beginnen, werden vom Server an Client Nr. 2 gesendet. Der Befehl „end“ schließt die Verbindung vom Server zum Client. In unserer Antwort haben wir uns auf die folgenden HTTP-Header beschränkt:
HTTP/1.1 200 OK
2 : Server: serveur tcp generique
2 : Connection: close
2 : Content-Type: text/html
2 :
Wir geben die Größe der zu sendenden Datei (Content-Length) nicht an, sondern weisen lediglich darauf hin, dass wir die Verbindung (Connection: close) nach dem Senden schließen werden. Dies reicht für den Browser aus. Sobald er sieht, dass die Verbindung geschlossen wurde, weiß er, dass die Antwort des Servers vollständig ist, und zeigt die ihm gesendete HTML-Seite an. Die Seite sieht wie folgt aus:
2 : <html>
2 : <head><title>Serveur generique</title></head>
2 : <body>
2 : <center>
2 : <h2>Reponse du serveur generique</h2>
2 : </center>
2 : </body>
2 : </html>
Der Benutzer schließt dann die Verbindung zum Client, indem er den Befehl „fin“ eingibt. Der Browser erkennt daraufhin, dass die Antwort des Servers vollständig ist, und kann sie anzeigen:

Wenn Sie oben „Ansicht/Quelltext“ auswählen, um zu sehen, was der Browser empfangen hat, erhalten Sie:

das heißt, genau das, was vom generischen Server gesendet wurde.
Der Code für den generischen TCP-Server lautet wie folgt:
// paquetages
import java.io.*;
import java.net.*;
public class serveurTCPgenerique{
// programme principal
public static void main (String[] args){
// reçoit le port d'écoute des demandes des clients
// crée un thread pour lire les demandes du client
// celles-ci seront affichées à l'écran
// crée un thread pour lire des commandes tapées au clavier
// celles-ci seront envoyées comme réponse au client
// le tout se termine avec la commande fin tapée au clavier
final String syntaxe="Syntaxe : pg port";
// variable d'instance
// y-a-t-il un argument
if(args.length != 1)
erreur(syntaxe,1);
// le port doit être entier >0
int port=0;
boolean erreurPort=false;
Exception E=null;
try{
port=Integer.parseInt(args[0]);
}catch(Exception e){
E=e;
erreurPort=true;
}
erreurPort=erreurPort || port <=0;
if(erreurPort)
erreur(syntaxe+"\n"+"Port incorrect ("+E+")",2);
// on crée le servive d'écoute
ServerSocket ecoute=null;
int nbClients=0; // nbre de clients traités
try{
// on crée le service
ecoute=new ServerSocket(port);
// suivi
System.out.println("Serveur générique lancé sur le port " + port);
// boucle de service aux clients
Socket client=null;
while (true){ // boucle infinie - sera arrêtée par Ctrl-C
// attente d'un client
client=ecoute.accept();
// le service est assuré des threads séparés
nbClients++;
// on crée les threads de lecture/écriture
new ServeurSend(client,nbClients).start();
new ServeurReceive(client,nbClients).start();
// on retourne à l'écoute des demandes
}// fin while
}catch(Exception ex){
// on signale l'erreur
erreur("L'erreur suivante s'est produite : " + ex.getMessage(),3);
}//catch
}// fin main
// affichage des erreurs
public static void erreur(String msg, int exitCode){
// affichage erreur
System.err.println(msg);
// arrêt avec erreur
System.exit(exitCode);
}//erreur
}//classe
class ServeurSend extends Thread{
// classe chargée de lire des réponses tapées au clavier
// et de les envoyer à un client via un client tcp passé au constructeur
Socket client; // le client tcp
int numClient; // n° de client
// constructeur
public ServeurSend(Socket client, int numClient){
// on note le client tcp
this.client=client;
// et son n°
this.numClient=numClient;
}//constructeur
// méthode Run du thread
public void run(){
// données locales
PrintWriter OUT=null; // flux d'écriture réseau
String réponse=null; // réponse lue au clavier
BufferedReader IN=null; // flux clavier
// suivi
System.out.println("Thread de lecture des réponses du serveur au client "+ numClient + " lancé");
// gestion des erreurs
try{
// création du flux d'écriture réseau
OUT=new PrintWriter(client.getOutputStream(),true);
// création du flux clavier
IN=new BufferedReader(new InputStreamReader(System.in));
// boucle saisie-envoi des commandes
while(true){
// identification client
System.out.print("--> " + numClient + " : ");
// lecture réponse tapée au clavier
réponse=IN.readLine().trim();
// fini ?
if (réponse.toLowerCase().equals("fin")) break;
// envoi réponse au serveur
OUT.println(réponse);
// réponse suivante
}//while
}catch(Exception ex){
// erreur
System.err.println("L'erreur suivante s'est produite : " + ex.getMessage());
}//catch
// fin - on ferme les flux
try{
OUT.close();client.close();
}catch(Exception ex){}
// on signale la fin du thread
System.out.println("[fin du Thread de lecture des réponses du serveur au client "+ numClient+ "]");
}//run
}//classe
class ServeurReceive extends Thread{
// classe chargée de lire les lignes de texte envoyées au serveur
// via un client tcp passé au constructeur
Socket client; // le client tcp
int numClient; // n° de client
// constructeur
public ServeurReceive(Socket client, int numClient){
// on note le client tcp
this.client=client;
// et son n°
this.numClient=numClient;
}//constructeur
// méthode Run du thread
public void run(){
// données locales
BufferedReader IN=null; // flux lecture réseau
String réponse=null; // réponse serveur
// suivi
System.out.println("Thread de lecture des demandes du client "+ numClient + " lancé");
// gestion des erreurs
try{
// création du flux lecture réseau
IN=new BufferedReader(new InputStreamReader(client.getInputStream()));
// boucle lecture lignes de texte du flux IN
while(true){
// lecture flux réseau
réponse=IN.readLine();
// flux fermé ?
if(réponse==null) break;
// affichage
System.out.println("<-- "+réponse);
}//while
}catch(Exception ex){
// erreur
System.err.println("L'erreur suivante s'est produite : " + ex.getMessage());
}//catch
// fin - on ferme les flux
try{
IN.close();client.close();
}catch(Exception ex){}
// on signale la fin du thread
System.out.println("[fin du Thread de lecture des demandes du client "+ numClient+"]");
}//run
}//classe
8.3. JAVASCRIPT
In diesem Abschnitt stellen wir drei Beispiele für die Verwendung von JavaScript in Webseiten vor. Wir konzentrieren uns auf die Formularverarbeitung, aber JavaScript kann noch viel mehr.
8.3.1. Abrufen von Informationen aus einem Formular
Das folgende Beispiel zeigt, wie man Daten abruft, die der Benutzer in ein Formular im Browser eingegeben hat. Dies ermöglicht in der Regel eine Vorverarbeitung, bevor die Daten an den Server gesendet werden.
8.3.1.1. Das Formular
Wir haben ein Formular, das die gängigsten Komponenten enthält, sowie eine Schaltfläche „Anzeigen“, mit der Sie die Eingaben des Benutzers anzeigen können.

8.3.1.2. Der Code
<html>
<head>
<title>Un formulaire traité par Javascript</title>
<script language="javascript">
function afficher(){
// affiche dans une liste les infos du formulaire
// on efface d'abord
effacerInfos();
// on affiche la valeur des # champs
with(document.frmExemple){
// champ caché
ecrire("champ caché="+cache.value);
// champ textuel simple
ecrire("champ textuel simple="+simple.value);
// champ textuel multiple
ecrire("champ textuel multiple="+lignes.value);
// boutons radio
for(i=0;i<radio.length;i++){
texte="radio["+i+"]="+radio[i].value;
if(radio[i].checked) texte+=", coché";
ecrire(texte);
}//for
// cases à cocher
for(i=0;i<qcm.length;i++){
texte="qcm["+i+"]="+qcm[i].value;
if(qcm[i].checked) texte+=", coché";
ecrire(texte);
}//for
//liste déroulante
ecrire("index sélectionné dans le menu="+menu.selectedIndex);
for(i=0;i<menu.length;i++){
texte="menu["+i+"]="+menu.options[i].text;
if(menu.options[i].selected) texte+=",sélectionné";
ecrire(texte);
}//for
//liste à choix multiple
for(i=0;i<lstVoitures.length;i++){
texte="lstVoitures["+i+"]="+lstVoitures.options[i].text;
if(lstVoitures.options[i].selected) texte+=",sélectionné";
ecrire(texte);
}//for
//mot de passe
ecrire("mot de passe="+passwd.value);
}//with
}//function
function ecrire(texte){
// écrit texte dans la liste des infos
frmInfos.lstInfos.options[frmInfos.lstInfos.length]=new Option(texte);
}//écrire
function effacerInfos(){
frmInfos.lstInfos.length=0;
}//effacerInfos
</script>
</head>
<body bgcolor="#C0C0C0" onload="afficher()">
<center>
<h2>Un formulaire traité par Javascript</h2>
<hr>
<form method="POST" name="frmExemple">
<input type="hidden" name="cache" value="secret">
<table border="0">
<tr>
<td align="center">Un champ textuel simple</td>
<td align="center" width="100"> </td>
<td align="center">Un champ textuel sur plusieurs lignes</td>
</tr>
<tr>
<td align="center"><input type="text" size="20" name="simple"></td>
<td align="center" width="100"> </td>
<td align="center">
<textarea name="lignes" rows="2" cols="40">Ce texte est modifiable</textarea>
</td>
</tr>
</table>
<table border="0">
<tr>
<td><strong>Des boutons radio :</strong></td>
<td>
<input type="radio" checked name="radio" value="FM">FM
</td>
<td>
<input type="radio" name="radio" value="GO">GO
</td>
<td>
<input type="radio" name="radio" value="PO">PO
</td>
<td> </td>
<td><strong>Des choix multiples :</strong></td>
<td>
<input type="checkbox" name="qcm" value="un">un
</td>
<td>
<input type="checkbox" name="qcm" value="deux">deux
</td>
<td>
<input type="checkbox" name="qcm" value="trois">trois
</td>
</tr>
</table>
<table border="0">
<tr>
<td>Un menu déroulant : </td>
<td>
<select name="menu" size="1">
<option>50 F</option>
<option>60 F</option>
<option>70 F</option>
<option>100 F</option>
</select>
</td>
<td>Une liste :</td>
<td>
<select name="lstVoitures" multiple size="3">
<option>Renault</option>
<option>Citroën</option>
<option>Peugeot</option>
<option>Fiat</option>
<option>Audi</option>
</select>
</td>
</tr>
</table>
<table border="0">
<tr>
<td>Un mot de passe : </td>
<td><input type="password" size="21" name="passwd"></td>
<td> </td>
<td>Un champ de contexte caché : </td>
</tr>
</table>
</form>
<hr>
<h2>Informations du formulaire</h2>
<form name="frmInfos">
<table>
<tr>
<td><input type="button" value="Effacer" onclick="effacerInfos()"></td>
<td>
<select name="lstInfos" multiple size="3">
</select>
</td>
<td>
<input type="button" name="cmdAfficher" value="Afficher" onclick="afficher()">
</td>
</tr>
</form>
</body>
</html>
8.3.2. Reguläre Ausdrücke in JavaScript
Auf der Browserseite kann JavaScript verwendet werden, um vom Benutzer eingegebene Daten zu validieren, bevor sie an den Server gesendet werden. Hier ist ein Programm zum Testen dieser regulären Ausdrücke.
8.3.2.1. Die Testseite

8.3.2.2. Der Seitencode
<html>
<head>
<title>Les expressions régulières en Javascript</title>
<script language="javascript">
function afficherInfos(){
with(document.frmRegExp){
// qq chose à faire ?
if (! verifier()) return;
// c'est bon - on efface les résultats précédents
effacerInfos();
// vérification du modèle
modele=new RegExp(txtModele.value);
champs=modele.exec(txtChaine.value);
if(champs==null)
// pas de correspondance entre modèle et chaîne
ecrireInfos("pas de correspondance");
else{
// correspondance - on affiche les résultats obtenus
ecrireInfos("Il y a correspondance");
for(i=0;i<champs.length;i++)
ecrireInfos("champs["+i+"]=["+champs[i]+"]");
}//else
}//with
}//function
function ecrireInfos(texte){
// écrit texte dans la liste des infos
document.frmRegExp.lstInfos.options[document.frmRegExp.lstInfos.length]=new Option(texte);
}//écrire
function effacerInfos(){
frmRegExp.lstInfos.length=0;
}//effacerInfos
function jouer(){
// teste le modèle contre la chaîne dans l'exemple choisi
with(document.frmRegExp){
txtModele.value=lstModeles.options[lstModeles.selectedIndex].text
txtChaine.value=lstChaines.options[lstChaines.selectedIndex].text
afficherInfos();
}//with
}//jouer
function ajouter(){
//ajoute le test courant aux exemples
with(document.frmRegExp){
// qq chose à faire ?
if (! verifier()) return;
// ajout
lstModeles.options[lstModeles.length]=new Option(txtModele.value);
lstChaines.options[lstChaines.length]=new Option(txtChaine.value);
// raz saisies
txtModele.value="";
txtChaine.value="";
}//with
}//ajouter
function verifier(){
// vérifie que les champs de saisie sont non vides
with(document.frmRegExp){
champs=/^\s*$/.exec(txtModele.value);
if(champs!=null){
alert("Vous n'avez pas indiqué de modèle");
txtModele.focus();
return false;
}//if
champs=/^\s*$/.exec(txtChaine.value);
if(champs!=null){
alert("Vous n'avez pas indiqué de chaîne de test");
txtChaine.focus();
return false;
}//if
// c'est bon
return true;
}//with
}//verifier
</script>
</head>
<body bgcolor="#C0C0C0">
<center>
<h2>Les expressions régulières en Javascript</h2>
<hr>
<form name="frmRegExp">
<table>
<tr>
<td>Expression régulière</td>
<td>Chaîne de test</td>
</tr>
<tr>
<td><input type="text" name="txtModele" size="20"></td>
<td><input type="text" name="txtChaine" size="20"></td>
</tr>
<tr>
<td>
<input type="button" name="cmdAfficher" value="Jouer le test" onclick="afficherInfos()">
</td>
<td>
<input type="button" name="cmdAjouter" value="Ajouter aux exemples" onclick="ajouter()">
</td>
</tr>
</table>
<hr>
<h2>Résultats de l'instruction champs=expression régulière.exec(chaine)</h2>
<table>
<tr>
<td>
<select name="lstInfos" size="3">
</select>
</td>
</tr>
</table>
<hr>
<h2>Exemples</h2>
<table>
<tr>
<td align="center">Modèles</td>
<td align="center">Chaînes</td>
</tr>
<tr>
<td>
<select name="lstModeles" size="1">
<option>^\d+$</option>
<option>^(\d+) (\d+)$</option>
<option>^(\d+)(.*)(\d+)$</option>
<option>^(\d+)(\s+)(\d+)$</option>
</select>
</td>
<td>
<select name="lstChaines" size="1">
<option>67</option>
<option>56 84</option>
<option>45abcd67</option>
<option>45 67</option>
</select>
</td>
<td>
<input type="button" name="cmdJouer" value="Jouer l'exemple" onclick="jouer()">
</td>
</tr>
</form>
</body>
</html>
8.3.3. Listenverwaltung in JavaScript
8.3.3.1. Das Formular

8.3.3.2. Der Code
<html>
<head>
<title>Les listes en Javascript</title>
<script language="javascript">
// ajouter
function ajouter(L1,L2,T){
// ajoute la valeur du champ T aux listes L1,L2
// qq chose à faire ?
champs=/^\s*$/.exec(T.value);
if(champs!=null){
// le champ est vide
alert("Vous n'avez pas indiqué la valeur à ajouter");
txtElement.focus();
return;
}//if
// on ajoute l'élément
L1.options[L1.length]=new Option(T.value);
L2.options[L2.length]=new Option(T.value);
T.value="";
}//ajouter
//vider
function vider(L){
// vide la liste L
L.length=0;
}//vider
//transfert
function transfert(L1,L2,simple){
//transfére dans L2 les éléments sélectionnés dans la liste L1
// qq chose à faire ?
// index de l'élément sélectionné dans L1
index1=L1.selectedIndex;
if(index1==-1){
alert("Vous n'avez pas sélectionné d'élément");
return;
}//if
// quel est le mode de sélection des éléments des listes
if(simple){ // sélection simple
element1=L1.options[index1].text;
//ajout dans L2
L2.options[L2.length]=new Option(element1);
//suppression dans L1
L1.options[index1]=null;
}//simple
if(! simple){ //sélection multiple
//on parcourt la liste 1 en sens inverse
for(i=L1.length-1;i>=0;i--){
//élément sélectionné ?
if(L1.options[i].selected){
//on l'ajoute à L2
L2.options[L2.length]=new Option(L1.options[i].text);
//on le supprime de L1
L1.options[i]=null;
}//if
}//for i
}//if ! simple
}//transfert
</script>
</head>
<body bgcolor="#C0C0C0">
<center>
<h2>Les listes en Javascript</h2>
<hr>
<form name="frmListes">
<table>
<tr>
<td>
<input type="button" name="cmdAjouter" value="Ajouter" onclick="ajouter(lst1A,lst1B,txtElement)">
</td>
<td>
<input type="text" name="txtElement">
</td>
</tr>
</table>
<table>
<tr>
<td align="center">liste 1</td>
<td align="center"><input type="button" value=">>" onclick="transfert(lst1A,lst2A,true)"</td>
<td align="center"><input type="button" value="<<" onclick="transfert(lst2A,lst1A,true)"</td>
<td align="center">liste 2</td>
<td width="30"></td>
<td align="center">liste 1</td>
<td align="center"><input type="button" value=">>" onclick="transfert(lst1B,lst2B,false)"</td>
<td align="center"><input type="button" value="<<" onclick="transfert(lst2B,lst1B,false)"</td>
<td align="center">liste 2</td>
</tr>
<tr>
<td></td>
<td align="center">
<select name="lst1A" size="5">
</select>
</td>
<td align="center">
<select name="lst2A" size="5">
</select>
</td>
<td></td>
<td></td>
<td></td>
<td align="center">
<select name="lst1B" size="5" multiple >
</select>
</td>
<td align="center">
<select name="lst2B" size="5" multiple>
</select>
</td>
</tr>
<tr>
<td></td>
<td align="center"><input type="button" value="Vider" onclick="vider(lst1A)"</td>
<td align="center"><input type="button" value="Vider" onclick="vider(lst2A)"</td>
<td></td>
<td></td>
<td></td>
<td align="center"><input type="button" value="Vider" onclick="vider(lst1B)"</td>
<td align="center"><input type="button" value="Vider" onclick="vider(lst2B)"</td>
<td></td>
</tr>
<tr>
<td></td>
<td colspan="2"><strong>Sélection simple</strong></td>
<td></td>
<td></td>
<td></td>
<td colspan="2"><strong>Sélection multiple</strong></td>
<td></td>
</tr>
</table>
<hr>
</form>
</body>
</html>


