Skip to content

8. Appendices

8.1. Web Development Tools

Here we indicate where to find and how to install the tools necessary for web development. Some tools have seen their versions evolve, and it is possible that the explanations provided here no longer apply to the most recent versions. The reader will then need to adapt... In the web programming course, we will primarily use the following tools, all available for free:

  • a recent browser capable of displaying XML. The examples in the course have been tested with Internet Explorer 6.
  • A recent JDK (Java Development Kit). The examples in this course have been tested with JDK 1.4. This JDK includes the Java 1.4 browser plug-in, which allows browsers to display Java applets using JDK 1.4.
  • A Java development environment for writing Java servlets. Here, it is JBuilder 7.
  • Web servers: Apache, PWS (Personal Web Server), Tomcat.
    • Apache will be used for developing web applications in PERL (Practical Extracting and Reporting Language) or PHP (Personal Home Page)
    • PWS will be used for developing web applications in ASP (Active Server Pages) or PHP
    • Tomcat will be used for developing web applications using Java servlets or JSP (Java Server Pages)
  • A database management application: MySQL
  • EasyPHP: a tool that bundles the Apache web server, the PHP language, and the MySQL DBMS

8.1.1. Web Servers, Browsers, Scripting Languages

  1. Major Web Servers
    • Apache (Linux, Windows)
    • Internet Information Server (IIS) (NT), Personal Web Server (PWS) (Windows 9x)
  1. Major browsers
    • Internet Explorer (Windows)
    • Netscape (Linux, Windows)
  1. Server-side scripting languages
    • VBScript (IIS, PWS)
    • JavaScript (IIS, PWS)
    • Perl (Apache, IIS, PWS)
    • PHP (Apache, IIS, PWS)
    • Java (Apache, Tomcat)
    • .NET languages
  1. Client-side scripting languages
    • VBScript (IE)
    • JavaScript (IE, Netscape)
    • PerlScript (IE)
    • Java (IE, Netscape)

8.1.2. Where to find the tools

Netscape
http://www.netscape.com/ (downloads link)
Internet Explorer
http://www.microsoft.com/windows/ie/default.asp
PHP
http://www.php.net
http://www.php.net/downloads.php (Windows Binaries)
PERL
http://www.activestate.com http://www.activestate.com/Products/
http://www.activestate.com/Products/ActivePerl/
VBScript, JavaScript
http://msdn.microsoft.com/scripting (follow the Windows Script link)
JAVA
http://java.sun.com/
http://java.sun.com/downloads.html (JSE)
http://java.sun.com/j2se/1.4/download.html
Apache
http://www.apache.org/
http://www.apache.org/dist/httpd/binaries/win32/
PWS
included in the NT 4.0 Option Pack for Windows 95
included on the Windows 98 CD
http://www.microsoft.com/ntserver/nts/downloads/recommended/NT4OptPk/win95.asp
IIS
(Windows NT/2000)
http://www.microsoft.com
Tomcat
http://jakarta.apache.org/tomcat/
JBuilder
http://www.borland.com/jbuilder/
http://www.borland.com/products/downloads/download_jbuilder.html
EasyPHP
http://www.easyphp.org/
http://www.easyphp.org/telechargements.php3

8.1.3. EasyPHP

This application is very convenient because it includes the following in a single package:

  • the Apache Web server (1.3.x)
  • the PHP language (4.x)
  • the MySQL DBMS (3.23.x)
  • a MySQL administration tool: PhpMyAdmin

The installation application looks like this:

Image

Installing EasyPHP is straightforward, and a directory structure is created in the file system:

Image

easyphp.exe
the application executable
apache
the Apache server directory structure
mysql
the MySQL database directory
phpMyAdmin
the phpMyAdmin application directory structure
PHP
the PHP directory structure
www
root of the directory tree for web pages served by the EasyPHP Apache server
cgi-bin
directory where you can place CGI scripts for the Apache server

The main advantage of EasyPHP is that the application comes preconfigured. Thus, Apache, PHP, and MySQL are already configured to work together. When you launch EasyPHP via its shortcut in the Programs menu, an icon appears in the bottom-right corner of the screen.

This is the letter E with a red dot, which should flash if the Apache web server and the MySQL database are operational. When you right-click on it, you access the menu options:

Image

The Administration option allows you to configure settings and run functionality tests:

Image

8.1.3.1. PHP Administration

The PHP Info button should allow you to verify that the Apache-PHP combination is working properly: a PHP information page should appear:

Image

The Extensions button displays a list of installed PHP extensions. These are actually function libraries.

Image

The screen above shows, for example, that the functions required to use the MySQL database are present.

The Settings button displays the username and password for the MySQL database administrator.

Image

Using the MySQL database is beyond the scope of this quick overview, but it is clear here that a password should be set for the database administrator.

8.1.3.2. Apache Administration

Still on the EasyPHP administration page, the "Your Aliases" link allows you to define aliases associated with a directory. This lets you place web pages outside the www directory in the EasyPHP directory structure.

Image

If you enter the following information on the page above:

Image

and click the "Validate" button, the following lines are added to the <easyphp>\apache\conf\httpd.conf file:

    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> refers to the EasyPHP installation directory. httpd.conf is the Apache server configuration file. You can therefore achieve the same result by editing this file directly. Changes to the httpd.conf file are normally applied immediately by Apache. If this is not the case, you will need to stop and restart the server, using the EasyPHP icon:

Image

To finish our example, we can now place web pages in the directory tree e:\data\serge\web:

C:\winnt\system32>dir e:\data\serge\web\html\balises.htm

07/14/2002  5:02 PM                3,767 tags.htm

and request this page using the alias st:

Image

In this example, the Apache server has been configured to run on port 81. Its default port is 80. This is controlled by the following line in the httpd.conf file we’ve already seen:

Port 81

8.1.3.3. The Apache configuration file htpd.conf

When you want to fine-tune Apache, you have to manually edit its httpd.conf configuration file, located here in the <easyphp>\apache\conf folder:

Image

Here are a few key points to note in this configuration file:

line(s)
role
ServerRoot "D:/Program Files/Apache Group/Apache"
specifies the folder containing the Apache directory tree
Port 80
specifies which port the web server will use. Typically, this is 80. By changing this line, you can have the web server run on a different port
ServerAdmin root@istia.univ-angers.fr
the email address of the Apache server administrator
ServerName stahe.istia.uang
the name of the machine on which the Apache server is running
ServerRoot "E:/Program Files/EasyPHP/apache"
the installation directory of the Apache server. When relative file names appear in the configuration file, they are relative to this directory.
DocumentRoot "E:/Program Files/EasyPHP/www"
the root directory of the tree of web pages served by the server. Here, the URL http://machine/rep1/fic1.html will correspond to the file E:\Program Files\EasyPHP\www\rep1\fic1.html
<Directory "E:/Program Files/EasyPHP/www">
sets the properties of the previous folder
ErrorLog logs/error.log
logs folder, so effectively <ServerRoot>\logs\error.log: E:\Program Files\EasyPHP\apache\logs\error.log. This is the file to check if you find that the Apache server is not working.
    ScriptAlias /cgi-bin/ "E:/Program Files/EasyPHP/cgi-bin/"
E:\Program Files\EasyPHP\cgi-bin will be the root of the directory tree where you can place CGI scripts. Thus, the URL http://machine/cgi-bin/rep1/script1.pl will be the URL for the CGI script E:\Program Files\EasyPHP\cgi-bin\rep1\script1.pl.
<Directory "E:/Program Files/EasyPHP/cgi-bin/">
sets the properties of the folder above
LoadModule php4_module "E:/Program
 Files/EasyPHP/php/php4apache.dll"
AddModule mod_php4.c
Lines for loading modules that allow Apache to work with PHP4.
    AddType application/x-httpd-php
 .phtml .pwml .php3
.php4 .php .php2 .inc
sets the file extensions to be treated as PHP files

8.1.3.4. MySQL Administration with PhpMyAdmin

On the EasyPHP administration page, click the PhpMyAdmin button:

Image

The drop-down list under Home allows you to view the
.
The number in parentheses is the number of tables. If you
select a database, its tables are displayed:

The web page offers a number of operations on the database:

Image

If you click the View user link:

Image

There is only one user here: root, who is the MySQL administrator. By following the Edit link, you could change their password, which is currently blank—a practice not recommended for an administrator.

We won’t say any more about phpMyAdmin, which is a feature-rich program that would merit a discussion spanning several pages.

8.1.4. PHP

We have seen how to obtain PHP through the EasyPHP application. To obtain PHP directly, go to the website http://www.php.net.

PHP isn’t limited to web use. You can use it as a scripting language on Windows. Create the following script and save it as date.php:

<?
  // PHP script displaying the time
  $now = date("j/m/y, H:i:s", time());
  echo "Today is $maintenant";
?>

In a DOS window, navigate to the directory containing date.php and run it:

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

Today is 07/18/02, 09:31:01

8.1.5. PERL

It is best if Internet Explorer is already installed. If it is present, Active Perl will configure it to accept PERL scripts in HTML pages, scripts that will be executed by IE itself on the client side. The Active Perl website is at the URL http://www.activestate.comA installation, PERL will be installed in a directory we will call <perl>. It contains the following directory structure:

DEISL1   ISU        32 403  06/23/00  17:16 DeIsL1.isu
BIN            <REP>        06/23/00  17:15 bin
LIB            <REP>        06/23/00  5:15 PM lib
HTML           <REP>        06/23/00  5:15 PM html
EG             <REP>        06/23/00  5:15 PM eg
SITE           <REP>        06/23/00  5:15 PM site
HTMLHELP       <REP>        06/28/00  6:37 PM htmlhelp

The perl.exe executable is located in <perl>\bin. Perl is a scripting language that runs on Windows and Unix. It is also used in web programming. Let’s write our first script:

# PERL script displaying the time

# modules
use strict;

# program
my ($seconds, $minutes, $hour) = localtime(time);
print "It is $hour:$minutes:$seconds\n";

Save this script to a file named heure.pl. Open a DOS window, navigate to the directory containing the script, and run it:

E:\data\serge\Perl\Essais>e:\perl\bin\perl.exe heure.pl
It is 9:34:21

8.1.6. VBScript, JavaScript, PerlScript

These are scripting languages for Windows. They can run in various environments such as

  • Windows Scripting Host for direct use in Windows, particularly for writing system administration scripts
  • Internet Explorer. It is then used within HTML pages, to which it adds a level of interactivity that cannot be achieved with HTML alone.
  • Internet Information Server (IIS), Microsoft’s web server on NT/2000, and its equivalent, Personal Web Server (PWS), on Win9x. In this case, VBScript is used for server-side web programming, a technology called ASP (Active Server Pages) by Microsoft.

Download the installation file from the URL: http://msdn.microsoft.com/scripting and follow the Windows Script links. The following are installed:

  • the Windows Scripting Host container, which supports various scripting languages such as VBScript and JavaScript, as well as others like PerlScript, which is included with Active Perl.
  • a VBScript interpreter
  • a JavaScript interpreter

Let’s run a few quick tests. Let’s build the following VBScript program:

' a class
class person
  Dim name
  Dim age
End class

' Create a Person object
Set p1 = New Person
With p1
  .name="dupont"
  .age = 18
End With

' Display properties of person p1
With p1
  wscript.echo "name=" & .name
  wscript.echo "age=" & .age
End With

This program uses objects. Let's call it objects.vbs (the .vbs extension indicates a VBScript file). Navigate to the directory where it is located and run it:

E:\data\serge\windowsScripting\vbscript\poly\objects>cscript objects.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

name=dupont
age=18

Now let's build the following JavaScript program that uses arrays:

// array in a variant
// empty array
array = new Array();
display(array);
// array grows dynamically
for(i=0;i<3;i++){
  array.push(i*10);
}
// display array
display(array);
// again
for(i=3;i<6;i++){
  array.push(i*10);
}
display(array);

// multi-dimensional arrays
WScript.echo("-----------------------------");

array2 = new Array();
for(i=0;i<3;i++){
  array2.push(new Array());
  for(j=0;j<4;j++){
    array2[i].push(i*10+j);
  }//for j
}// for i
display2(array2);

// end
WScript.quit(0);

// ---------------------------------------------------------
function display(array){
  // display array
  for(i=0;i<array.length;i++){
    WScript.echo("array[" + i + "]=" + array[i]);
  }//for
}//function

// ---------------------------------------------------------
function display2(array){
  // display array
  for(i=0;i<array.length;i++){
    for(j=0;j<array[i].length;j++){
      WScript.echo("array[" + i + "," + j + "]=" + array[i][j]);
    }// for j
  }//for i
}//function

This program uses arrays. Let's call it arrays.js (the .js suffix indicates a JavaScript file). Navigate to the directory where it is located and run it:

E:\data\serge\windowsScripting\javascript\poly\tableaux>cscript tableaux.js
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

array[0]=0
tableau[1]=10
array[2]=20
array[0] = 0
array[1] = 10
array[2] = 20
array[3] = 30
array[4] = 40
array[5] = 50
-----------------------------
array[0,0] = 0
array[0,1] = 1
array[0,2] = 2
array[0,3] = 3
array[1,0] = 10
array[1,1] = 11
array[1,2] = 12
array[1,3] = 13
array[2,0] = 20
array[2,1] = 21
array[2,2] = 22
array[2,3] = 23

One last example in PerlScript to finish up. You must have Active Perl installed to access PerlScript.

<job id="PERL1">
  <script language="PerlScript">
      # Classic Perl
    %dico=("maurice"=>"juliette","philippe"=>"marianne");
    @keys = keys %dico;
    for ($i=0;$i<=$#keys;$i++){
        $key=$keys[$i];
      $value = $dico{$key};
        $WScript->echo ("key=".$key.", value=".$value);
    }
    # Perl script using Windows Script objects
    $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>

This program demonstrates the creation and use of two dictionaries: one in the classic Perl style, the other using the Windows Script Scripting Dictionary object. Let’s save this code to the file dico.wsf (wsf is the file extension for Windows Script files). Navigate to the program’s folder and run it:

E:\data\serge\windowsScripting\perlscript\essais>cscript dico.wsf
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

key=philippe, value=marianne
key=maurice, value=juliette
juliette
marianne

PerlScript can use objects from the container in which it runs. Here, these were objects from the Windows Script container. In the context of web programming, VBScript, JavaScript, and PerlScript scripts can be executed either within the IE browser or on a PWS or IIS server. If the script is somewhat complex, it may be wise to test it outside the web context, within the Windows Script container as seen previously. This way, you can only test the script’s functions that do not use browser- or server-specific objects. Even with this restriction, this option remains useful because it is generally quite impractical to debug scripts running within web servers or browsers.

8.1.7. JAVA

Java is available at the URL: http://www.sun.com and is installed in a directory structure called <java> that contains the following elements:

May 22, 2002  5:51 AM       <DIR>          .
05/22/2002  05:51       <DIR>          ..
05/22/2002  05:51       <DIR>          bin
05/22/2002  05:51       <DIR>          jre
02/07/2002  12:52                8,277 README.txt
02/07/2002  12:52               13,853 LICENSE
02/07/2002  12:52                4,516 COPYRIGHT
02/07/2002  12:52               15,290 readme.html
05/22/2002  05:51       <DIR>          lib
05/22/2002  05:51       <DIR>          include
05/22/2002  05:51       <DIR>          demo
02/07/2002  12:52           10 377 848 src.zip
02/11/2002  12:55       <DIR>          docs

In the bin directory, you will find javac.exe, the Java compiler, and java.exe, the Java Virtual Machine. You can perform the following tests:

  1. Write the following script:
//Java program displaying the time

import java.io.*;
import java.util.*;

public class time{
  public static void main(String arg[]){
     // Get the date and time
     Date now = new Date();
     // display
     System.out.println("It is " + now.getHours() +
        ":" + now.getMinutes() + ":" + now.getSeconds());
  }//main
}//class
  1. Save this program as heure.java. Open a DOS window. Navigate to the directory containing the heure.java file and compile it:
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.

In the command above, c:\jdk1.3\bin\javac must be replaced with the exact path to the javac.exe compiler. You should now have a file named heure.class in the same directory as heure.java; this is the program that will now be executed by the java.exe virtual machine.

  1. Run the program:
D:\data\java\essais>c:\jdk1.3\bin\java heure
It is 10:44:2

8.1.8. Apache Server

We have seen that the Apache server can be obtained through the EasyPHP application. To download it directly, go to the Apache website: http://www.apache.org. The installation creates a directory structure containing all the files necessary for the server. Let’s call this directory <apache>. It contains a directory structure similar to the following:

UNINST   ISU       118 805  06/23/00  17:09 Uninst.isu
HTDOCS         <REP>        06/23/00  5:09 PM htdocs
APACHE~1 DLL       299,008  02/25/00  9:11 PM ApacheCore.dll
ANNOUN~1             3,000  02/23/00  16:51 Announcement
ABOUT_~1            13,197  03/31/99  6:42 PM ABOUT_APACHE
APACHE   EXE        20,480  02/25/00  21:04 Apache.exe
KEYS                36,437  08/20/99  11:57 KEYS
LICENSE              2,907  01/01/99  13:04 LICENSE
MAKEFI~1 TMP        27,370  01/11/00  1:47 PM Makefile.tmpl
README               2,109  04/01/98   6:59 README
README   NT          3,223  03/19/99   9:55 README.NT
WARNIN~1 TXT           339  09/21/98  1:09 PM WARNING-NT.TXT
BIN            <REP>        06/23/00  17:09 bin
MODULES        <REP>        06/23/00  17:09 modules
ICONS          <REP>        06/23/00  5:09 PM icons
LOGS           <REP>        06/23/00  5:09 PM logs
CONF           <REP>        06/23/00  5:09 PM conf
CGI-BIN        <REP>        06/23/00  5:09 PM cgi-bin
PROXY          <REP>        06/23/00  5:09 PM proxy
INSTALL  LOG         3,779  06/23/00  5:09 PM install.log
conf
Apache configuration files directory
logs
Apache log files (monitoring) directory
bin
Apache executables

8.1.8.1. Configuration

In the <Apache>\conf directory, you will find the following files: httpd.conf, srm.conf, access.conf. In the latest versions of Apache, these three files have been combined into httpd.conf. We have already covered the key points of this configuration file. In the following examples, the Apache version of EasyPHP was used for testing, and therefore its configuration file. In this file, DocumentRoot, which designates the root of the web page directory tree, is e:\program files\easyphp\www.

To test, create the file intro.php with the following single line:

<? phpinfo() ?>

and place it at the root of the Apache server’s web pages (DocumentRoot above). Request the URL http://localhost/intro.php. You should see a list of PHP information:

Image

The following PHP script displays the time. We’ve seen it before:

<?php
  // time: number of milliseconds since 01/01/1970
  // "date-time display format
  // d: day (2 digits)
  // m: 2-digit month
  // y: 2-digit year
  // H: hour 0,23
  // i: minutes
  // s: seconds
  print "Today is " . date("d/m/y H:i:s",time());
?>

Place this text file in the root directory of the Apache server (DocumentRoot) and name it date.php. Open a browser and enter the URL http://localhost/date.php. You will see the following page:

Image

This is achieved using a line of the form: ScriptAlias /cgi-bin/ "E:/Program Files/EasyPHP/cgi-bin/" in the file <apache>\conf\httpd.conf. Its syntax is ScriptAlias /cgi-bin/ "<cgi-bin>" where <cgi-bin> is the folder where CGI scripts can be placed. CGI (Common Gateway Interface) is a standard for communication between the web server and applications. A client requests a dynamic page from the web server, i.e., a page generated by a program. The web server must therefore instruct a program to generate the page. CGI defines the interaction between the server and the program, specifically how information is transmitted between these two entities.

If necessary, modify the line ScriptAlias /cgi-bin/ &quot;&lt;cgi-bin&gt;&quot; and restart the Apache server. Then perform the following test:

  1. Write the script:
#!c:\perl\bin\perl.exe

# PERL script displaying the time

# modules
use strict;

# program
my ($seconds, $minutes, $hour) = localtime(time);
print <<FINHTML
Content-Type: text/html

<html>
 <head>
  <title>time</title>
 </head>
 <body>
  <h1>It is $hour:$minutes:$seconds</h1>
 </body>
ENDHTML
;
  1. Place this script in <cgi-bin>\heure.pl, where <cgi-bin> is the directory that can receive CGI scripts (see httpd.conf). The first line, #!c:\perl\bin\perl.exe, specifies the path to the perl.exe executable. Modify it if necessary.
  2. Start Apache if you haven't already
  3. Request the URL http://localhost/cgi-bin/heure.pl in a browser. You will see the following page:

Image

8.1.9. The PWS server

8.1.9.1. Installation

The PWS (Personal Web Server) is a personal version of Microsoft's IIS (Internet Information Server). IIS is available on NT and 2000 machines. On Win9x machines, PWS is normally included in the Internet Explorer installation package. However, it is not installed by default. You must perform a custom installation of IE and request the installation of PWS. It is also available in the NT 4.0 Option Pack for Windows 95.

8.1.9.2. Initial Tests

The root directory for PWS web pages is drive:\inetpub\wwwroot, where drive is the disk on which you installed PWS. We will assume hereafter that this drive is D. Thus, the URL http://machine/rep1/page1.html corresponds to the file d:\inetpub\wwwroot\rep1\page1.html. The PWS server interprets any file with the .asp (Active Server Pages) extension as a script that it must execute to generate an HTML page.

PWS runs on port 80 by default. The Apache web server does too... You must therefore stop Apache to work with PWS if you have both servers. The other solution is to configure Apache to run on a different port. In the Apache configuration file httpd.conf, replace the line Port 80</mark> with Port 81</mark>. Apache will now run on port 81 and can be used simultaneously with PWS. If PWS is running and you request the URL http://localhost, you will see a page similar to the following:

Image

  1. Below is a .reg file for modifying the registry. Double-click this file to modify the registry. Here, the required DLL is located in d:\php4 along with the PHP executable. Modify as needed. The backslashes (\) must be doubled in the DLL path.
REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map]
".php"="d:\\php4\\php4isapi.dll"
  1. Restart the machine so that the registry change takes effect.
  1. Create a "php" folder in d:\inetpub\wwwroot, which is the root of the PWS server. Once done, open PWS and go to the "Advanced" tab. Click the "Add" button to create a virtual directory:
Directory/Browse: d:\inetpub\wwwroot\php
Alias: php
Check the "Run" box.
  1. Confirm the settings and restart PWS. Place the file intro.php in d:\inetpub\wwwroot\php, containing only the following line:
<? phpinfo() ?>
  1. Request the URL http://localhost/php/intro.php from the PWS server. You should see the list of PHP information already displayed with Apache.

8.1.10. Tomcat: Java servlets and JSP (Java Server Pages)

Tomcat is a web server that generates HTML pages using servlets (Java programs executed by the web server) or JSP (Java Server Pages), which combine Java code with HTML code. It is the equivalent of ASP (Active Server Pages) on Microsoft’s IIS/PWS server, where VBScript or JavaScript code is combined with HTML code.

8.1.10.1. Installation

Tomcat is available at the URL: http://jakarta.apache.org. You will download an .exe installation file. When you run this program, it first prompts you to select which JDK it will use. This is because Tomcat requires a JDK to install itself and subsequently to compile and execute Java servlets. You must therefore have a Java JDK installed before installing Tomcat. The most recent JDK is recommended. The installation will create a <tomcat> directory structure:

Image

which simply involves extracting this archive into a directory. Choose a directory whose path contains only names without spaces (not, for example, "Program Files"), because there is a bug in the Tomcat installation process. Use, for example, C:\tomcat or D:\tomcat. Let’s call this directory <tomcat>. Inside it, you will find a folder named jakarta-tomcat, and within that folder, the following directory structure:

LOGS           <REP>        11/15/00   9:04 logs
LICENSE              2,876  04/18/00  15:56 LICENSE
CONF           <REP>        11/15/00   8:53 conf
DOC            <REP>        11/15/00   8:53 doc
LIB            <REP>        11/15/00   8:53 lib
SRC            <REP>        11/15/00   8:53 src
WEBAPPS        <REP>        11/15/00   8:53 webapps
BIN            <REP>        11/15/00   8:53 bin
WORK           <REP>        11/15/00   9:04 work

8.1.10.2. Starting/Stopping the Tomcat Web Server

Tomcat is a web server, just like Apache or PWS. To launch it, use the links in the Programs menu:

Start Tomcat
to start Tomcat
Stop Tomcat
to stop it

When you start Tomcat, a DOS window appears with the following content:

Image

You can minimize this DOS window. It will remain open as long as Tomcat is running. You can then proceed to the first tests. The Tomcat web server runs on port 8080. Once Tomcat is running, open a web browser and enter the URL http://localhost:8080. You should see the following page:

Image

Follow the Servlet Examples link:

Image

Click the Execute link for RequestParameters, then the one for Source. You’ll get a first glimpse of what a Java servlet is. You can do the same with the links on the JSP pages.

To stop Tomcat, use the Stop Tomcat link in the Programs menu.

8.1.11. JBuilder

JBuilder is a Java application development environment. To build Java servlets without graphical interfaces, such an environment is not strictly necessary. A text editor and a JDK will suffice. However, JBuilder offers a few advantages over the previous method:

  • ease of debugging: the compiler highlights erroneous lines in a program, and it is easy to navigate to them
  • code completion: when using a Java object, JBuilder displays a list of its properties and methods inline. This is very useful, given that most Java objects have numerous properties and methods that are difficult to remember.

JBuilder can be found at http://www.borland.com/jbuilder. You must fill out a form to obtain the software. An activation key is sent via email. To install JBuilder 7, for example, the following steps were taken:

  • Three ZIP files were downloaded: one for the application, one for the documentation, and one for the examples. Each of these ZIP files has a separate link on the JBuilder website.
  • First, the application was installed, then the documentation, and finally the examples
  • When you launch the application for the first time, an activation key is requested: this is the one that was sent to you via email. In version 7, this key is actually an entire text file that can be placed, for example, in the JB7 installation folder. When the key is requested, you then specify the file in question. Once this is done, the key will not be requested again.

There are a few useful configurations to set up if you want to use JBuilder to build Java servlets. The so-called "Personal" version of JBuilder is a stripped-down version that does not include all the classes necessary for Java web development. You can configure JBuilder to use the class libraries provided by Tomcat. Here’s how:

  • Launch JBuilder

Image

  • enable the Tools/Configure JDKs option

Image

In the JDK Settings section above, the Name field typically displays "JDK 1.3.1." If you have a newer JDK, use the Change button to specify its installation directory. In the example above, we have specified the directory E:\Program Files\jdk14, where a JDK 1.4 was installed. From now on, JBuilder will use this JDK for its compilations and executions. In the (Class, Source, Documentation) section, you’ll see a list of all the class libraries that JBuilder will scan—in this case, the classes from JDK 1.4. The classes included in this JDK are not sufficient for Java web development. To add other class libraries, use the Add button and specify the additional .jar files you want to use. .jar files are class libraries. Tomcat 4.x includes all the class libraries necessary for web development. They are located in <tomcat>\common\lib, where <tomcat> is the Tomcat installation directory:

Image

Using the Add button, we will add these libraries, one by one, to the list of libraries scanned by JBuilder:

Image

From now on, you can compile Java programs compliant with the J2EE standard, including Java servlets. JBuilder is used only for compilation; execution is subsequently handled by Tomcat according to the procedures explained in the course.

8.2. Program source code

8.2.1. The generic TCP client

Many services created at the dawn of the Internet operate according to the echo server model studied earlier: client-server communication occurs via the exchange of text lines. We will write a generic TCP client that will be launched as follows: java cltTCPgenerique server port

This TCP client will connect to port port on server server. Once connected, it will create two threads:

  1. a thread responsible for reading commands typed on the keyboard and sending them to the server
  2. a thread responsible for reading the server’s responses and displaying them on the screen

Why two threads? Each TCP-IP service has its own specific protocol, and the following situations sometimes arise:

  • the client must send several lines of text before receiving a response
  • a server’s response may contain multiple lines of text

Therefore, the loop that sends a single line to the server and receives a single line from the server is not always suitable. We will therefore create two separate loops:

  • a loop to read commands typed on the keyboard to be sent to the server. The user will signal the end of commands with the keyword "fin".
  • a loop to receive and display the server’s responses. This will be an infinite loop that will only be interrupted by the server closing the network connection or by the user typing the “end” command at the keyboard.

To have these two separate loops, we need two independent threads. Let’s look at an example of execution where our generic TCP client connects to an SMTP (Simple Mail Transfer Protocol) service. This service is responsible for routing email to its recipients. It operates on port 25 and uses a text-based exchange protocol.

Dos>java genericTCPclient istia.univ-angers.fr 25
Commands:
<-- 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

line1
line2
line3
.
<-- 250 2.0.0 g4D6bks25951 Message accepted for delivery
quit
<-- 221 2.0.0 istia.univ-angers.fr closing connection
[end of thread reading server responses]
end
[end of the thread sending commands to the server]

Let's comment on these client-server exchanges:

  • The SMTP service sends a welcome message when a client connects to it:
<-- 220 istia.univ-angers.fr ESMTP Sendmail 8.11.6/8.9.3; Mon, 13 May 2002 08:37:26 +0200
  • Some services have a "help" command that provides information on the commands available for that service. That is not the case here. The SMTP commands used in the example are as follows:
    • mail from: sender, to specify the sender’s email address
    • rcpt to: recipient, to specify the email address of the message’s recipient. If there are multiple recipients, the rcpt to: command is repeated as many times as necessary for each recipient.
    • data, which signals to the SMTP server that the message is about to be sent. As indicated in the server’s response, this is a sequence of lines ending with a line containing only a period. A message may have headers separated from the message body by a blank line. In our example, we included a subject using the Subject: keyword
  • Once the message is sent, we can tell the server that we are done using the quit command. The server then closes the network connection. The read thread can detect this event and stop.
  • The user then types "end" on the keyboard to also stop the thread reading the commands typed on the keyboard.

If we check the received email, we see the following (Outlook):

Image

Note that the SMTP service cannot detect whether a sender is valid or not. Therefore, you can never trust the "From" field of a message. In this case, the sender machin@univ-angers.fr did not exist.

This generic TCP client allows us to explore the communication protocol for Internet services and, from there, build specialized classes for clients of those services. Let’s explore the communication protocol for the POP (Post Office Protocol) service, which allows users to retrieve their emails stored on a server. It operates on port 110.

Dos> java clientTCPgenerique istia.univ-angers.fr 110
Commands:
<-- +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 mypassword
<-- +OK st has 157 visible messages (0 hidden) in 11,755,927 bytes.
list
<-- +OK 157 visible messages (11,755,927 bytes)
<-- 1 892847
<-- 2 171,661
...
<-- 156 2,843
<-- 157 2,796
<-- .
retr 157
<-- +OK 2796 bytes
<-- 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, May 13, 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, May 13, 2002 08:58:28 +0200 (CEST)
...
<-- ------------------------------------------------------------------------
<-- NOC-RENATER2                  Tel.  : 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.
[end of thread reading server responses]
end
[end of thread for sending commands to the server]

The main commands are as follows:

  • user login, where you enter your login on the machine that hosts your emails
  • pass password, where you enter the password associated with the previous login
  • list, to get a list of messages in the format number, size in bytes
  • retr i, to read message number i
  • quit, to end the session.

Let’s now explore the communication protocol between a client and a web server, which typically runs on port 80:

Dos> java clientTCPgenerique istia.univ-angers.fr 80
Commands:
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>Welcome to ISTIA - University of Angers</title>
<-- </head>
....
<-- face="Verdana"> - Last updated on <b>January 10, 2002</b></font></p>
<-- </body>
<-- </html>
<--
[end of thread displaying server responses]
end
[end of the thread for sending commands to the server]

A web client sends its commands to the server according to the following pattern:

command1
command2
...
commands
[empty line]

The web server responds only after receiving the empty line. In this example, we used only one command:

GET /index.html HTTP/1.0

which requests the URL /index.html from the server and indicates that it is using HTTP version 1.0. The most recent version of this protocol is 1.1. The example shows that the server responded by sending the contents of the index.html file and then closed the connection, as we can see the response reading thread terminating. Before sending the contents of the index.html file, the web server sent a series of headers followed by an empty line:

<-- 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>

The line <html> is the first line of the /index.html file. The preceding text is called HTTP (HyperText Transfer Protocol) headers. We won’t go into detail about these headers here, but keep in mind that our generic client provides access to them, which can be helpful for understanding them. For example, the first line:

<-- HTTP/1.1 200 OK

indicates that the contacted web server supports the HTTP/1.1 protocol and that it successfully found the requested file (200 OK), where 200 is an HTTP response code. The lines

<-- Content-Length: 11251
<-- Connection: close
<-- Content-Type: text/html

tell the client that it will receive 11,251 bytes of HTML (HyperText Markup Language) text and that the connection will be closed once the data has been sent.

So here we have a very handy TCP client. It certainly does less than the official telnet program, but it was interesting to write it ourselves. The generic TCP client program is as follows:

// imported packages
import java.io.*;
import java.net.*;

public class genericTCPclient{

    // receives the characteristics of a service as a parameter in the form
    // server port
    // connects to the service
    // creates a thread to read commands typed on the keyboard
    // these will be sent to the server
    // creates a thread to read responses from the server
    // these will be displayed on the screen
    // the process ends when the "end" command is typed

  // instance variable
  private static Socket client;

    public static void main(String[] args){

        // syntax
        final String syntax = "pg server port";

        // number of arguments
        if(args.length != 2)
            error(syntax, 1);

        // note the server name
        String server = args[0];

        // the port must be an integer greater than 0
        int port = 0;
        boolean portError = false;
        Exception e = null;
        try{
            port = Integer.parseInt(args[1]);
        } catch (Exception e) {
            E = e;
            errorPort=true;
        }
        portError = portError || port <= 0;
        if(portError)
            error(syntax + "\n" + "Incorrect port (" + E + ")", 2);

        client = null;
        // there may be issues
        try{
            // connect to the service
            client = new Socket(server, port);
        } catch (Exception ex) {
            // error
            error("Unable to connect to the service ("+ server
                +","+port+"), error: "+ex.getMessage(),3);
            // end
            return;
        }//catch

        // create read/write threads
    new ClientSend(client).start();
    new ClientReceive(client).start();

        // end of main thread
        return;
    }// main

    // display errors
    public static void error(String msg, int exitCode){
        // display error
        System.err.println(msg);
        // exit with error
        System.exit(exitCode);
    }//error
}//class  

class ClientSend extends Thread {
    // class responsible for reading commands typed on the keyboard
    // and sending them to a server via a TCP client passed as a parameter

    private Socket client;    // the TCP client

    // constructor
    public ClientSend(Socket client){
        // store the TCP client
        this.client = client;
    }//constructor

    // thread's Run method
    public void run(){

        // local data
        PrintWriter OUT = null;            // network write stream
    BufferedReader IN = null;        // keyboard stream
        String command = null;            // Command read from the keyboard

        // error handling
        try{
            // Create network write stream
            OUT = new PrintWriter(client.getOutputStream(), true);
      // create keyboard input stream
      IN = new BufferedReader(new InputStreamReader(System.in));
            // loop for command input and transmission
            System.out.println("Commands: ");
            while(true){
                // Read command typed on the keyboard
                command = IN.readLine().trim();
                // Done?
                if (command.toLowerCase().equals("end")) break;
                // send command to server
                OUT.println(command);
                // next command
            }//while
        } catch (Exception ex) {
            // error
            System.err.println("Sending: The following error occurred: " + ex.getMessage());
        }//catch
        // end - closing the streams
        try{
            OUT.close(); client.close();
        }catch(Exception ex){}
        // signal the end of the thread
        System.out.println("[Send: end of the thread sending commands to the server]");
    }//run
}//class

class ClientReceive extends Thread{
    // class responsible for reading text lines intended for a 
    // TCP client passed as a parameter

    private Socket client;    // the TCP client

    // constructor
    public ClientReceive(Socket client){
        // store the TCP client
        this.client = client;
    }//constructor

    // thread's Run method
    public void run(){

        // local data
        BufferedReader IN = null;        // network read stream
        String response = null;        // Server response

        // error handling
        try{
            // Create network read stream
            IN = new BufferedReader(new InputStreamReader(client.getInputStream()));
            // Loop to read text lines from the IN stream
            while(true){
                // read network stream
                response = IN.readLine();
                // Is the stream closed?
                if(response == null) break;
                // display
                System.out.println("<-- " + response);
            }//while
        } catch (Exception ex) {
            // error
            System.err.println("Reception: The following error occurred: " + ex.getMessage());
        }//catch
        // end - closing the streams
        try{
            IN.close(); client.close();
        }catch(Exception ex){}
        // signal the end of the thread
        System.out.println("[Receive: end of thread reading responses from the server]");
    }//run
}//class

8.2.2. The generic TCP server

Now we'll look at a server

  • that displays on the screen the commands sent by its clients
  • and sends them, in response, the lines of text typed on the keyboard by a user. It is therefore the user who acts as the server.

The program is launched by: java genericTCPserver listeningPort, where listeningPort is the port to which clients must connect. Client service will be handled by two threads:

  • one thread dedicated exclusively to reading the text lines sent by the client
  • a thread dedicated exclusively to reading the responses typed on the keyboard by the user. This thread will signal, using the `fin` command, that it is closing the connection with the client.

The server creates two threads per client. If there are n clients, there will be 2n active threads at the same time. The server itself never stops unless the user presses Ctrl-C on the keyboard. Let’s look at a few examples.

The server is running on port 100, and we use the generic client to communicate with it. The client window looks like this:


E:\data\serge\MSNET\c#\network\generic tcp client> java genericTCPclient localhost 100
Commands:
command 1 from client 1
<-- response 1 to client 1
command 2 from client 1
<-- response 2 to client 1
end
The following error occurred: Unable to read data from the transport connection.
[end of thread reading server responses]
[end of the thread sending commands to the server]

Lines beginning with <-- are those sent from the server to the client; the others are from the client to the server. The server window is as follows:


Dos> java genericTCPserver 100
Generic server launched on port 100
Thread for reading server responses to client 1 launched
1: Thread for reading requests from client 1 started
<-- Request 1 from Client 1
Response 1 to Client 1
1: <-- Request 2 from Client 1
Response 2 to Client 1
1: [End of thread reading requests from client 1]
end
[end of thread reading server responses to client 1]

Lines beginning with <-- are those sent from the client to the server. Lines N: are those sent from the server to client N. The server above is still active even though client 1 has finished. We launch a second client for the same server:


Dos> java clientTCPgenerique localhost 100
Commands:
command 3 from client 2
<-- response 3 to client 2
end
The following error occurred: Unable to read data from the transport connection.
[end of thread reading server responses]
[end of the thread sending commands to the server]

The server window then looks like this:


Dos> java genericTCPserver 100
Generic server launched on port 100
Thread for reading server responses to client 1 launched
1: Thread for reading requests from client 1 launched
<-- command 1 from client 1
Response 1 to client 1
1: <-- command 2 from client 1
response 2 to client 1
1: [End of thread reading requests from client 1]
end
[end of thread reading server responses to client 1]
Thread for reading server responses to client 2 launched
2: Thread for reading requests from client 2 launched
<-- command 3 from client 2
response 3 to client 2
2: [End of thread reading requests from client 2]
end
[end of thread reading server responses to client 2]
^C

Now let's simulate a web server by running our generic server on port 88:


Dos> java genericTCPserver 88
Generic server launched on port 88

Now let’s open a browser and request the URL http://localhost:88/exemple.html. The browser will then connect to port 88 on the localhost machine and request the /example.html page:

Image

Now let’s look at our server window:

Dos>java genericTCPserver 88
Generic server launched on port 88
Thread for reading server responses to client 2 launched
2: Thread for reading requests from client 2 launched
<-- GET /example.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
<--

This reveals the HTTP headers sent by the browser. This allows us to gradually learn about the HTTP protocol. In a previous example, we created a web client that sent only the GET command. That was sufficient. Here we see that the browser sends other information to the server. This information is intended to tell the server what type of client it is dealing with. We also see that the HTTP headers end with a blank line.

Let’s craft a response for our client. The user at the keyboard is the actual server here and can manually craft a response. Recall the response sent by a web server in a previous example:

<-- 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>

Let's try to provide a similar response:

...
<-- Host: localhost:88
<-- Connection: Keep-Alive
<--
2: HTTP/1.1 200 OK
2: Server: generic TCP server
2: Connection: close
2: Content-Type: text/html
2:
2: <html>
2:   <head><title>Generic Server</title></head>
2:   <body>
2:     <center>
2:       <h2>Response from the generic server</h2>
2:     </center>
2:    </body>
2: </html>
2: end
The following error occurred: Unable to read data from the transport connection.
[end of thread reading requests from client 2]
[end of thread reading server responses to client 2]

Lines beginning with 2: are sent from the server to client #2. The end command closes the connection from the server to the client. In our response, we have limited ourselves to the following HTTP headers:

HTTP/1.1 200 OK
2: Server: generic TCP server
2: Connection: close
2: Content-Type: text/html
2 :

We do not specify the size of the file we are sending (Content-Length), but simply indicate that we will close the connection (Connection: close) after sending it. This is sufficient for the browser. Upon seeing the connection closed, it will know that the server’s response is complete and will display the HTML page that was sent to it. The page is as follows:

2: <html>
2:   <head><title>Generic server</title></head>
2:   <body>
2:     <center>
2:       <h2>Response from the generic server</h2>
2:     </center>
2:    </body>
2: </html>

The user then closes the connection to the client by typing the "fin" command. The browser then knows that the server's response is complete and can display it:

Image

If you select View/Source above to see what the browser received, you get:

Image

that is, exactly what was sent from the generic server.

The code for the generic TCP server is as follows:

// packages
import java.io.*;
import java.net.*;

public class genericTCPserver{

    // main program
    public static void main(String[] args) {

    // receives the port to listen for client requests
    // creates a thread to read client requests
    // these will be displayed on the screen
    // creates a thread to read commands typed on the keyboard
    // these will be sent as a response to the client
    // the process ends with the "end" command typed on the keyboard

    final String syntax = "Syntax: pg port";
  // instance variable
         // is there an argument
     if(args.length != 1)
        error(syntax, 1);

        // the port must be an integer > 0
        int port = 0;
        boolean portError = false;
        Exception E = null;
        try {
            port = Integer.parseInt(args[0]);
        } catch (Exception e) {
            E = e;
            portError=true;
        }
        portError = portError || port <= 0;
        if(portError)
            error(syntax + "\n" + "Incorrect port (" + E + ")", 2);

     // create the listening service
    ServerSocket listener = null;
    int clients = 0;    // number of clients handled
        try{
            // Create the service
            listen = new ServerSocket(port);
            // monitoring
            System.out.println("Generic server launched on port " + port);

            // service loop for clients
            Socket client = null;
            while (true){ // infinite loop - will be stopped by Ctrl-C
                // waiting for a client
                client = listener.accept();

                // the service is handled by separate threads
                nbClients++;

                // create read/write threads
        new ServerSend(client, nbClients).start();
        new ReceiveServer(client, nbClients).start();

                // return to listening for requests
            }// end of while
        } catch (Exception ex) {
            // report the error
            error("The following error occurred: " + ex.getMessage(), 3);
        }//catch
    }// end main

    // display errors
    public static void error(String msg, int exitCode){
        // display error
        System.err.println(msg);
        // exit with error
        System.exit(exitCode);
    }//error
}//class

class ServerSend extends Thread{
    // class responsible for reading keyboard input
    // and send them to a client via a TCP client passed to the constructor

    Socket client;    // the TCP client
    int clientNum;        // client number

    // constructor
    public ServerSend(ClientSocket, int clientNumber){
        // store the TCP client
        this.client = client;
        // and its number
        this.clientNumber = clientNumber;
    }//constructor

    // thread's Run method
    public void run(){

        // local data
        PrintWriter OUT = null;        // network write stream
        String response = null;        // response read from keyboard
    BufferedReader IN = null;    // keyboard stream

        // tracking
        System.out.println("Thread for reading server responses to client " + numClient + " started");
        // error handling
        try{
            // creation of network write stream
            OUT = new PrintWriter(client.getOutputStream(), true);
      // Create keyboard stream
      IN = new BufferedReader(new InputStreamReader(System.in));
            // loop for command input and transmission
            while(true){
                // client identification
                System.out.print("--> " + clientNumber + " : ");
                // read response typed on the keyboard
                response = IN.readLine().trim();
                // Done?
                if (response.toLowerCase().equals("end")) break;
                // send response to the server
                OUT.println(response);
                // next response
            }//while
        } catch (Exception ex) {
            // error
            System.err.println("The following error occurred: " + ex.getMessage());
        }//catch
        // end - close the streams
        try{
            OUT.close(); client.close();
        } catch (Exception ex) {}
        // signal the end of the thread
        System.out.println("[End of thread reading server responses to client " + numClient + "]");
    }//run
}//class

class ServerReceive extends Thread{
    // Class responsible for reading the text lines sent to the server 
    // via a TCP client passed to the constructor

    Socket client;    // the TCP client
    int clientNumber;        // client number

    // constructor
    public ServerReceive(ClientSocket, int clientNumber){
        // store the TCP client
        this.client = client;
        // and its number
        this.clientNumber = clientNumber;
    }//constructor

    // thread's Run method
    public void run(){

        // local data
        BufferedReader IN = null;        // network read stream
        String response = null;        // server response

        // monitoring
        System.out.println("Thread for reading requests from client " + numClient + " started");
        // error handling
        try{
            // Create network read stream
            IN = new BufferedReader(new InputStreamReader(client.getInputStream()));
            // Loop to read text lines from the IN stream
            while(true){
                // read network stream
                response = IN.readLine();
                // Is the stream closed?
                if(response == null) break;
                // display
                System.out.println("<-- " + response);
            }//while
        } catch (Exception ex) {
            // error
            System.err.println("The following error occurred: " + ex.getMessage());
        }//catch
        // end - close the streams
        try{
            IN.close(); client.close();
        } catch (Exception ex) {}
        // signal the end of the thread
        System.out.println("[End of thread reading client requests " + numClient + "]");
    }//run
}//class

8.3. JAVASCRIPT

In this section, we present three examples of using JavaScript in web pages. We focus on form handling, but JavaScript can do much more.

8.3.1. Retrieving information from a form

The example below shows how to retrieve data entered by the user in a form within the browser. This generally allows for pre-processing before sending the data to the server.

8.3.1.1. The form

We have a form containing the most common components and a "Display" button that allows you to view the user's entries.

Image

8.3.1.2. The code

<html>

  <head>
    <title>A form processed by JavaScript</title>
    <script language="javascript">
      function display(){
        // displays the form data in a list

        // First, clear the list
        clearInfo();

        // display the values of the # fields
        with(document.frmExample){
          // hidden field
          write("hidden field="+cache.value);
          // simple text field
          write("single text field="+simple.value);
          // multi-line text field
          write("multiple text field=" + lines.value);
          // radio buttons
          for(i=0;i<radio.length;i++){
            text = "radio[" + i + "] = " + radio[i].value;
            if(radio[i].checked) text+=", checked";
            write(text);
          }//for
          //  checkboxes
          for(i=0;i<qcm.length;i++){
            text = "qcm[" + i + "] =" + qcm[i].value;
            if(qcm[i].checked) text+=", checked";
            write(text);
          }//for
          //dropdown list
          write("index selected in the menu="+menu.selectedIndex);
          for(i=0;i<menu.length;i++){
            text="menu["+i+"]="+menu.options[i].text;
            if(menu.options[i].selected) text+=", selected";
            write(text);
          }//for
          //multiple-choice list
          for(i=0;i<lstCars.length;i++){
            text = "lstCars[" + i + "] = " + lstCars.options[i].text;
            if(lstCars.options[i].selected) text+=",selected";
            write(text);
          }//for
          //password
          write("password="+passwd.value);
        }//with
      }//function

      function write(text){
        // writes text to the info list
        frmInfos.lstInfos.options[frmInfos.lstInfos.length] = new Option(text);
      }//write

      function clearInfo(){
        frmInfo.lstInfo.length = 0;
      }//clearInfo
    </script>
  </head>

  <body bgcolor="#C0C0C0" onload="display()">
    <center>
     <h2>A form processed by JavaScript</h2>
    <hr>
    <form method="POST" name="frmExemple">
        <input type="hidden" name="cache" value="secret">
        <table border="0">
        <tr>
            <td align="center">A simple text field</td>
            <td align="center" width="100">&nbsp;</td>
            <td align="center">A multi-line text field</td>
        </tr>
        <tr>
            <td align="center"><input type="text" size="20" name="simple"></td>
            <td align="center" width="100">&nbsp;</td>
            <td align="center">
              <textarea name="lines" rows="2" cols="40">This text is editable</textarea>
            </td>
        </tr>
    </table>
    <table border="0">
      <tr>
       <td><strong>Radio buttons:</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>&nbsp;</td>
        <td><strong>Multiple choices:</strong></td>
        <td>
          <input type="checkbox" name="qcm" value="one">one
        </td>
        <td>
          <input type="checkbox" name="qcm" value="two">two
        </td>
        <td>
          <input type="checkbox" name="qcm" value="three">three
        </td>
     </tr>
    </table>
    <table border="0">
      <tr>
       <td>A drop-down menu: </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>A list:</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>Password: </td>
            <td><input type="password" size="21" name="passwd"></td>
            <td>&nbsp;</td>
            <td>A hidden context field: </td>
        </tr>
    </table>
    </form>
    <hr>
    <h2>Form information</h2>
    <form name="frmInfos">
      <table>
        <tr>
          <td><input type="button" value="Clear" onclick="clearInfo()"></td>
          <td>
            <select name="lstInfos" multiple size="3">
            </select>
          </td>
          <td>
            <input type="button" name="cmdDisplay" value="Display" onclick="display()">
          </td>
        </tr>
    </form>
  </body>
</html>

8.3.2. Regular Expressions in JavaScript

On the browser side, JavaScript can be used to validate user-entered data before sending it to the server. Here is a program to test these regular expressions.

8.3.2.1. The test page

Image

8.3.2.2. The page code

<html>

  <head>
    <title>Regular expressions in JavaScript</title>
    <script language="javascript">
      function displayInfo(){
        with(document.regexp){
          // anything to do?
          if (!verify()) return;
          // All good—clear the previous results
          clearInfo();
          // check the pattern
          pattern = new RegExp(txtPattern.value);
          fields = pattern.exec(txtString.value);
          if(fields == null)
            // no match between pattern and string
            writeInfo("no match");
          else{
            // match - display the results
            writeInfo("There is a match");
            for(i=0;i<fields.length;i++)
              writeInfo("fields[" + i + "] = [" + fields[i] + "]");
          }//else
        }//with
      }//function

      function writeInfo(text) {
        // writes text to the info list
        document.frmRegExp.lstInfos.options[document.frmRegExp.lstInfos.length] = new Option(text);
      }//write

      function clearInfo(){
        frmRegExp.lstInfos.length = 0;
      }//clearInfo

      function play(){
        // checks the pattern against the string in the selected example
        with(document.frmRegExp){
          txtPattern.value = lstPatterns.options[lstPatterns.selectedIndex].text
          txtString.value = lstStrings.options[lstStrings.selectedIndex].text
          displayInfo();
        }//with
      }//play

      function add(){
        //adds the current test to the examples
        with(document.frmRegExp){
          // anything to do?
          if (!verify()) return;
          // add
          lstModeles.options[lstModeles.length] = new Option(txtModele.value);
          lstChains.options[lstChains.length] = new Option(txtChain.value);
          // Clear entries
          txtModel.value = "";
          txtString.value = "";
        }//with
      }//add

      function verify(){
        // checks that the input fields are not empty
        with(document.frmRegExp){
          fields = /^\s*$/.exec(txtModel.value);
          if(fields!=null){
            alert("You did not specify a template");
            txtModel.focus();
            return false;
          }//if
          fields = /^\s*$/ .exec(txtString.value);
          if(champs!=null){
            alert("You did not specify a test string");
            txtChain.focus();
            return false;
          }//if
          // OK
          return true;
        }//with
      }//check
    </script>
  </head>

  <body bgcolor="#C0C0C0">
    <center>
     <h2>Regular Expressions in JavaScript</h2>
    <hr>
    <form name="frmRegExp">
      <table>
        <tr>
          <td>Regular expression</td>
          <td>Test string</td>
        </tr>
        <tr>
          <td><input type="text" name="txtPattern" size="20"></td>
          <td><input type="text" name="txtString" size="20"></td>
        </tr>
        <tr>
          <td>
            <input type="button" name="cmdAfficher" value="Play the test" onclick="displayInfo()">
          </td>
          <td>
            <input type="button" name="cmdAdd" value="Add to examples" onclick="add()">
          </td>
        </tr>
      </table>
      <hr>
      <h2>Results of the statement fields=regular_expression.exec(string)</h2>
      <table>
        <tr>
          <td>
            <select name="lstInfos" size="3">
            </select>
          </td>
        </tr>
      </table>
      <hr>
      <h2>Examples</h2>
      <table>
 <tr>
          <td align="center">Templates</td>
          <td align="center">Channels</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="cmdPlay" value="Play example" onclick="play()">
          </td>
        </tr>
    </form>
  </body>
</html>

8.3.3. List Management in JavaScript

8.3.3.1. The form

Image

8.3.3.2. The code

<html>

  <head>
    <title>Lists in JavaScript</title>

    <script language="javascript">
      // add
      function add(L1, L2, T) {
        // adds the value of field T to lists L1, L2
          // anything to do?
          fields = /^\s*$/.exec(T.value);
          if(fields!=null){
            // the field is empty
            alert("You did not specify the value to add");
            txtElement.focus();
            return;
          }//if
          // Add the element
          L1.options[L1.length] = new Option(T.value);
          L2.options[L2.length] = new Option(T.value);
          T.value="";
      }//add

      //clear
      function clear(L){
        // clears the list L
        L.length = 0;
      }//clear

     //transfer
      function transfer(L1, L2, single){
        //transfer the selected elements from list L1 to L2

        // anything to do?
        // index of the selected element in L1
        index1 = L1.selectedIndex;
        if(index1==-1){
          alert("You have not selected an item");
          return;
        }//if
        // What is the selection mode for list items?
        if(simple){ // single selection
          element1 = L1.options[index1].text;
          //add to L2
          L2.options[L2.length] = new Option(element1);
          // Remove from L1
          L1.options[index1] = null;
        }//single
        if(!simple){ //multiple selection
          //iterate through list 1 in reverse order
          for(i=L1.length-1;i>=0;i--){
            //Is the element selected?
            if(L1.options[i].selected){
              //add it to L2
              L2.options[L2.length] = new Option(L1.options[i].text);
              //Remove it from L1
              L1.options[i] = null;
            }//if
          }//for i
        }//if ! simple
      }//transfer
   </script>
  </head>

  <body bgcolor="#C0C0C0">
    <center>
     <h2>Lists in JavaScript</h2>
    <hr>
    <form name="frmListes">
      <table>
        <tr>
          <td>
            <input type="button" name="cmdAdd" value="Add" onclick="add(lst1A,lst1B,txtElement)">
          </td>
          <td>
            <input type="text" name="txtElement">
          </td>
        </tr>
      </table>
      <table>
        <tr>
          <td align="center">List 1</td>
          <td align="center"><input type="button" value=">>" onclick="transfer(lst1A,lst2A,true)"</td>
          <td align="center"><input type="button" value="<<" onclick="transfer(lst2A,lst1A,true)"</td>
          <td align="center">list 2</td>
          <td width="30"></td>
          <td align="center">List 1</td>
          <td align="center"><input type="button" value=">>" onclick="transfer(lst1B,lst2B,false)"</td>
          <td align="center"><input type="button" value="<<" onclick="transfer(lst2B,lst1B,false)"</td>
          <td align="center">List 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="Clear" onclick="clear(lst1A)"</td>
          <td align="center"><input type="button" value="Clear" onclick="clear(lst2A)"</td>
          <td></td>
          <td></td>
          <td></td>
          <td align="center"><input type="button" value="Clear" onclick="clear(lst1B)"</td>
          <td align="center"><input type="button" value="Clear" onclick="clear(lst2B)"</td>
          <td></td>
        </tr>
        <tr>
          <td></td>
          <td colspan="2"><strong>Single selection</strong></td>
          <td></td>
          <td></td>
          <td></td>
          <td colspan="2"><strong>Multiple selection</strong></td>
          <td></td>
        </tr>

      </table>
      <hr>
    </form>
  </body>
</html>