8. Anexos
8.1. Ferramentas de desenvolvimento web
Indicamos aqui onde encontrar e como instalar as ferramentas necessárias para o desenvolvimento web. Algumas ferramentas tiveram suas versões atualizadas e é possível que as explicações fornecidas aqui não sejam mais adequadas para as versões mais recentes. O leitor deverá, então, se adaptar... No curso de programação web, utilizaremos essencialmente as seguintes ferramentas, todas disponíveis gratuitamente:
- um navegador recente capaz de exibir XML. Os exemplos do curso foram testados com o Internet Explorer 6.
- um JDK (Java Development Kit) recente. Os exemplos do curso foram testados com o JDK 1.4. Este JDK traz consigo o plug-in Java 1.4 para navegadores, o que permite que estes exibam applets Java que utilizam o Java 1.4.
- Um ambiente de desenvolvimento Java para escrever servlets Java. Neste caso, trata-se do JBuilder 7.
- servidores web: Apache, PWS (Personal Web Server), Tomcat.
- O Apache será utilizado para o desenvolvimento de aplicativos web em PERL (Practical Extracting and Reporting Language) ou PHP (Personal Home Page)
- O PWS será utilizado para o desenvolvimento de aplicativos web em ASP (Active Server Pages) ou PHP
- O Tomcat será utilizado para o desenvolvimento de aplicativos web por meio de servlets Java ou páginas JSP (Java Server Pages)
- uma aplicação de gerenciamento de banco de dados: MySQL
- EasyPHP: uma ferramenta que integra o servidor web Apache, a linguagem PHP e o SGBD MySQL
8.1.1. Servidores Web, Navegadores, Linguagens de script
- Principais servidores web
- Apache (Linux, Windows)
- Interner Information Server IIS (NT), Personal Web Server PWS (Windows 9x)
- Principais navegadores
- Internet Explorer (Windows)
- Netscape (Linux, Windows)
- Linguagens de script do lado do servidor
- VBScript (IIS, PWS)
- JavaScript (IIS, PWS)
- Perl (Apache, IIS, PWS)
- PHP (Apache, IIS, PWS)
- Java (Apache, Tomcat)
- Linguagens .NET
- Linguagens de script do lado do navegador
- VBScript (IE)
- JavaScript (IE, Netscape)
- PerlScript (IE)
- Java (IE, Netscape)
8.1.2. Onde encontrar as ferramentas
http://www.netscape.com/ (link para downloads) | |
http://www.microsoft.com/windows/ie/default.asp | |
http://www.php.net http://www.php.net/downloads.php (Binários do Windows) | |
http://www.activestate.com http://www.activestate.com/Products/ http://www.activestate.com/Products/ActivePerl/ | |
http://msdn.microsoft.com/scripting (acesse o link do script do Windows) | |
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/ | |
incluído no pacote de opções NT 4.0 para Windows 95 incluído no CD do Windows 98 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
Este aplicativo é muito prático, pois reúne em um único pacote:
- o servidor Web Apache (1.3.x)
- a linguagem PHP (4.x)
- o SGBD MySQL (3.23.x)
- uma ferramenta de administração do MySQL: PhpMyAdmin
O aplicativo de instalação apresenta-se da seguinte forma:

A instalação do EasyPHP ocorre sem problemas e uma estrutura de diretórios é criada no sistema de arquivos:

o executável do aplicativo | |
a estrutura de diretórios do servidor Apache | |
a estrutura de diretórios do MySQL SGBD | |
a estrutura de diretórios do aplicativo phpMyAdmin | |
a estrutura de diretórios do php | |
Raiz da estrutura das páginas da web servidas pelo servidor Apache do EasyPHP | |
estrutura de diretórios onde é possível colocar os scripts CGI para o servidor Apache |
A principal vantagem do EasyPHP é que o aplicativo vem pré-configurado. Assim, o Apache, o PHP e o MySQL já estão configurados para funcionar em conjunto. Ao iniciar o EasyPhp por meio do atalho no menu de programas, um ícone é exibido no canto inferior direito da tela.
![]() |
É o “E” com um ponto vermelho que deve piscar se o servidor web Apache e o banco de dados MySQL estiverem operacionais. Ao clicar nele com o botão direito do mouse, você acessa as opções do menu:

A opção Administration permite realizar ajustes e testes de funcionamento:

8.1.3.1. Administração PHP
O botão “Informações PHP” deve permitir que você verifique o bom funcionamento da combinação Apache-PHP: uma página de informações PHP deve aparecer:

O botão “Extensões” exibe a lista das extensões instaladas para o PHP. Na verdade, trata-se de bibliotecas de funções.

A tela acima mostra, por exemplo, que as funções necessárias para o uso do banco de dados MySQL estão presentes.
O botão “Parâmetros” exibe o login/motdepasse do administrador do banco de dados MySQL.

A utilização do banco de dados MySQL vai além do escopo desta breve apresentação, mas fica claro aqui que seria necessário definir uma senha para o administrador do banco de dados.
8.1.3.2. Administração do Apache
Ainda na página de administração do EasyPHP, o link “seus aliases” permite definir aliases associados a um diretório. Isso permite colocar páginas da Web em outros locais que não o diretório www da árvore de diretórios do easyPhp.

Se, na página acima, inserirmos as seguintes informações:

e utilizarmos o botão valider, as seguintes linhas serão adicionadas ao arquivo <easyphp>\apache\conf\httpd.conf:
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> indica o diretório de instalação do EasyPHP. httpd.conf é o arquivo de configuração do servidor Apache. Portanto, é possível fazer o mesmo editando diretamente esse arquivo. Uma alteração no arquivo httpd.conf normalmente é aplicada imediatamente pelo Apache. Caso contrário, seria necessário pará-lo e reiniciá-lo, sempre usando o ícone do EasyPHP:

Para concluir nosso exemplo, agora podemos colocar páginas da web na estrutura de diretórios e:\data\serge\web:
e acessar essa página usando o alias st:

Neste exemplo, o servidor Apache foi configurado para operar na porta 81. Sua porta padrão é a 80. Esse aspecto é controlado pela seguinte linha do arquivo httpd.conf, já mencionado anteriormente:
8.1.3.3. O arquivo de configuração do Apache htpd.conf
Quando se deseja fazer um ajuste mais refinado no Apache, é necessário modificar “manualmente” seu arquivo de configuração httpd.conf, localizado aqui na pasta <easyphp>\apache\conf:

Aqui estão alguns pontos importantes a serem lembrados sobre esse arquivo de configuração:
função | |
indica a pasta onde está localizada a estrutura de diretórios do Apache | |
indica em qual porta o servidor web irá operar. Normalmente, é a porta 80. Ao alterar essa linha, é possível fazer com que o servidor web opere em outra porta | |
o endereço de e-mail do administrador do servidor Apache | |
o nome da máquina na qual o servidor Apache está “em execução” | |
o diretório de instalação do servidor Apache. Quando, no arquivo de configuração, aparecem nomes relativos de arquivos, eles são relativos a essa pasta. | |
a pasta raiz da árvore de páginas da Web servidas pelo servidor. Aqui, a URL http://machine/rep1/fic1.html corresponderá ao arquivo E:\Program Files\EasyPHP\www\rep1\fic1.html | |
define as propriedades da pasta anterior | |
pasta de logs, ou seja, na verdade <ServerRoot>\logs\error.log: E:\Program Files\EasyPHP\apache\logs\error.log. Esse é o arquivo que você deve consultar caso perceba que o servidor Apache não está funcionando. | |
E:\Program Files\EasyPHP\cgi-bin será a raiz da árvore de diretórios onde será possível colocar scripts CGI. Assim, o URL http://machine/cgi-bin/rep1/script1.pl será a URL do script CGI E:\Program Files\EasyPHP\cgi-bin\rep1\script1.pl. | |
define as propriedades da pasta acima | |
linhas de carregamento dos módulos que permitem que o Apache funcione com o PHP4. | |
define os sufixos dos arquivos que devem ser considerados como arquivos a serem processados pelo PHP |
8.1.3.4. Administração do MySQL com o PhpMyAdmin
Na página de administração do EasyPhp, clique no botão PhpMyAdmin:

A lista suspensa abaixo de Accueil permite visualizar os bancos de bancos de dados atuais. | ![]() |
O número entre parênteses corresponde ao número de tabelas. Ao escolher um banco de dados, as tabelas dele serão exibidas: | ![]() |
A página da Web oferece diversas operações no banco de dados:

Se clicarmos no link Afficher de user:

Aqui há apenas um usuário: root, que é o administrador do MySQL. Ao seguir o link Modifier, seria possível alterar sua senha, que atualmente está em branco, o que não é recomendado para um administrador.
Não falaremos mais sobre o PhpMyAdmin, que é um software robusto e que mereceria uma descrição de várias páginas.
8.1.4. PHP
Vimos como obter o PHP por meio do aplicativo EasyPhp. Para obter o PHP diretamente, acesse o site http://www.php.net.
O PHP não é utilizável apenas na Web. É possível usá-lo como linguagem de script no Windows. Crie o seguinte script e salve-o com o nome date.php:
<?
// script PHP exibindo a hora
$maintenant=date("j/m/y, H:i:s",time());
echo "Nous sommes le $maintenant";
?>
Na janela DOS, navegue até o diretório de date.php e execute-o:
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
É recomendável que o Internet Explorer já esteja instalado. Se estiver presente, o Active Perl irá configurá-lo para que aceite scripts PERL nas páginas HTML, scripts que serão executados pelo próprio IE no lado do cliente. O site do Active Perl é o URL http://www.activestate.comA. Após a instalação, o PERL será instalado em um diretório que chamaremos de <perl>. Ele contém a seguinte estrutura de diretórios:
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
O executável perl.exe está em <perl>\bin. O Perl é uma linguagem de script que funciona no Windows e no Unix. Além disso, é utilizado na programação do WEB. Vamos escrever um primeiro script:
# script PERL exibindo a hora
# módulos
use strict;
# programa
my ($secondes,$minutes,$heure)=localtime(time);
print "Il est $heure:$minutes:$secondes\n";
Salve este script em um arquivo chamado heure.pl. Abra uma janela DOS, navegue até o diretório do script anterior e execute-o:
8.1.6. VBScript, JavaScript, PerlScript
Essas linguagens são linguagens de script para o Windows. Elas podem ser executadas em diversos ambientes, como
- o Windows Scripting Host para uso direto no Windows, especialmente para escrever scripts de administração de sistemas
- Internet Explorer. Nesse caso, ele é utilizado em páginas HTML, às quais confere uma certa interatividade impossível de ser alcançada apenas com a linguagem HTML.
- Internet Information Server (IIS), o servidor Web da Microsoft no NT/2000, e seu equivalente, o Personal Web Server (PWS), no Win9x. Nesse caso, o VBScript é utilizado para programação no lado do servidor web, tecnologia denominada ASP (Active Server Pages) pela Microsoft.
Baixe o arquivo de instalação do URL: http://msdn.microsoft.com/scripting e siga os links do Windows Script. São instalados:
- o contêiner Windows Scripting Host, que permite o uso de diversas linguagens de script, como VBScript e JavaScript, além de outras, como PerlScript, que vem junto com o Active Perl.
- um interpretador VBscript
- um interpretador de JavaScript
Vamos apresentar alguns testes rápidos. Vamos criar o seguinte programa vbscript:
' uma classe
class personne
Dim nom
Dim age
End class
' criação de um objeto “pessoa”
Set p1=new personne
With p1
.nom="dupont"
.age=18
End With
' exibição das propriedades da pessoa p1
With p1
wscript.echo "nom=" & .nom
wscript.echo "age=" & .age
End With
Este programa utiliza objetos. Vamos chamá-lo de objets.vbs (o sufixo vbs indica um arquivo VBScript). Vamos acessar o diretório em que ele está localizado e executá-lo:
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
Agora, vamos criar o seguinte programa em JavaScript que utiliza matrizes:
// matriz em uma variante
// matriz vazia
tableau=new Array();
affiche(tableau);
// matriz que cresce dinamicamente
for(i=0;i<3;i++){
tableau.push(i*10);
}
// exibição de tabela
affiche(tableau);
// novamente
for(i=3;i<6;i++){
tableau.push(i*10);
}
affiche(tableau);
// tabelas multidimensionais
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);
// fim
WScript.quit(0);
// ---------------------------------------------------------
function affiche(tableau){
// exibição da tabela
for(i=0;i<tableau.length;i++){
WScript.echo("tableau[" + i + "]=" + tableau[i]);
}//para
}//função
// ---------------------------------------------------------
function affiche2(tableau){
// exibição da tabela
for(i=0;i<tableau.length;i++){
for(j=0;j<tableau[i].length;j++){
WScript.echo("tableau[" + i + "," + j + "]=" + tableau[i][j]);
}// para j
}//para i
}//função
Este programa utiliza matrizes. Vamos chamá-lo de tableaux.js (o sufixo js indica um arquivo JavaScript). Vamos acessar o diretório em que ele está localizado e executá-lo:
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
Um último exemplo em Perlscript para encerrar. É necessário ter o Active Perl instalado para ter acesso ao Perlscript.
<job id="PERL1">
<script language="PerlScript">
# do Perl clássico
%dico=("maurice"=>"juliette","philippe"=>"marianne");
@cles= keys %dico;
for ($i=0;$i<=$#chaves;$i++){
$cle=$cles[$i];
$valeur=$dico{$cle};
$WScript->echo ("clé=".$cle.", valeur=".$valeur);
}
# do PerlScript utilizando objetos do 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>
Este programa demonstra a criação e o uso de dois dicionários: um no estilo clássico do Perl e outro com o objeto Scripting Dictionary do Windows Script. Vamos salvar esse código no arquivo dico.wsf (wsf é a extensão dos arquivos do Windows Script). Vamos acessar a pasta deste programa e executá-lo:
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
O Perlscript pode utilizar os objetos do contêiner no qual está sendo executado. Neste caso, eram objetos do contêiner do Windows Script. No contexto da programação web, os scripts VBscript, JavaScript e Perlscript podem ser executados tanto no navegador IE quanto em um servidor PWS ou IIS. Se o script for um pouco complexo, pode ser aconselhável testá-lo fora do contexto da Web, no contêiner do Windows Script, conforme visto anteriormente. Dessa forma, só será possível testar as funções do script que não utilizam objetos específicos do navegador ou do servidor. Mesmo com essa restrição, essa possibilidade continua sendo interessante, pois geralmente é bastante impraticável depurar scripts em execução em servidores da Web ou navegadores.
8.1.7. JAVA
O Java está disponível no URL: http://www.sun.com e é instalado em uma estrutura de diretórios que chamaremos de <java>, que contém os seguintes elementos:
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
Na pasta bin, encontraremos o javac.exe, o compilador Java, e o java.exe, a máquina virtual Java. Poderemos realizar os seguintes testes:
- Escreva o seguinte script:
//programa Java que exibe a hora
import java.io.*;
import java.util.*;
public class heure{
public static void main(String arg[]){
// recuperando data e hora
Date maintenant=new Date();
// exibindo
System.out.println("Il est "+maintenant.getHours()+
":"+maintenant.getMinutes()+":"+maintenant.getSeconds());
}//main
}//classe
- Salve este programa com o nome heure.java. Abra uma janela DOS. Navegue até o diretório do arquivo heure.java e compile-o:
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.
No comando acima, c:\jdk1.3\bin\javac deve ser substituído pelo caminho exato do compilador javac.exe. Você deve obter, no mesmo diretório que o heure.java, um arquivo heure.class, que é o programa que agora será executado pela máquina virtual java.exe.
- Execute o programa:
8.1.8. Servidor Apache
Vimos que é possível obter o servidor Apache com o aplicativo EasyPhp. Para obtê-lo diretamente, acessaremos o site do Apache: http://www.apache.org. A instalação cria uma estrutura de diretórios onde se encontram todos os arquivos necessários para o servidor. Vamos chamar esse diretório de <apache>. Ele contém uma estrutura semelhante à seguinte:
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
pasta dos arquivos de configuração do Apache | |
pasta dos arquivos de log (monitoramento) do Apache | |
os executáveis do Apache |
8.1.8.1. Configuration
Na pasta <Apache>\conf, encontram-se os seguintes arquivos: httpd.conf, srm.conf, access.conf. Nas versões mais recentes do Apache, os três arquivos foram reunidos no httpd.conf. Já apresentamos os pontos importantes desse arquivo de configuração. Nos exemplos a seguir, foi utilizada para os testes a versão do Apache contida no EasyPhp e, portanto, seu arquivo de configuração. Nele, DocumentRoot, que indica a raiz da árvore de páginas da Web, é e:\program files\easyphp\www.
8.1.8.2. Link PHP - Apache
Para testar, crie o arquivo intro.php contendo apenas a seguinte linha:
<? phpinfo() ?>
e coloque-o na raiz das páginas do servidor Apache (DocumentRoot acima). Acesse o URL em http://localhost/intro.php. Deve aparecer uma lista de informações php:

O script PHP a seguir exibe a hora. Já o vimos anteriormente:
<?php
// time: número de milissegundos desde 01/01/1970
// "formato de exibição de data e hora
// d: dia com 2 dígitos
// m: mês com 2 dígitos
// y: ano com 2 dígitos
// H: hora 0,23
// i: minutos
// s: segundos
print "Nous sommes le " . date("d/m/y H:i:s",time());
?>
Vamos colocar esse arquivo de texto na raiz das páginas do servidor Apache (DocumentRoot) e chamá-lo de date.php. Acessemos, usando um navegador, o endereço http://localhost/date.phpURL. Obteremos a seguinte página:

8.1.8.3. Link PERL-APACHE
Ele é criado por meio de uma linha no formato: ScriptAlias /cgi-bin/ "E:/Program Files/EasyPHP/cgi-bin/" no arquivo <apache>\conf\httpd.conf. Sua sintaxe é ScriptAlias /cgi-bin/ "<cgi-bin>", onde <cgi-bin> é a pasta onde poderão ser colocados os scripts CGI. CGI (Common Gateway Interface) é um padrão de comunicação entre o servidor WEB e os aplicativos. Um cliente solicita ao servidor web uma página dinâmica, c.a.d, ou seja, uma página gerada por um programa. O servidor WEB deve, portanto, solicitar a um programa que gere a página. CGI define a comunicação entre o servidor e o programa, especialmente o modo de transmissão de informações entre essas duas entidades.
Se necessário, altere a linha ScriptAlias /cgi-bin/ "<cgi-bin>" e reinicie o servidor Apache. Em seguida, faça o seguinte teste:
- Escreva o script:
#!c:\perl\bin\perl.exe
# script PERL exibindo a hora
# módulos
use strict;
# programa
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
;
- Coloque este script em <cgi-bin>\heure.pl, onde <cgi-bin> é a pasta que pode receber scripts CGI (consulte httpd.conf). A primeira linha #!c:\perl\bin\perl.exe indica o caminho do executável perl.exe. Altere-o, se necessário.
- Inicie o Apache, caso ainda não tenha sido feito
- Acesse, usando um navegador, o arquivo URL em http://localhost/cgi-bin/heure.pl. Aparecerá a seguinte página:

8.1.9. O servidor PWS
8.1.9.1. Installation
O servidor PWS (Personal Web Server) é uma versão pessoal do servidor IIS (Internet Information Server) da Microsoft. Este último está disponível nos sistemas NT e 2000. Nos computadores com Win9x, o PWS normalmente está disponível no pacote de instalação do Internet Explorer. No entanto, ele não é instalado por padrão. É necessário realizar uma instalação personalizada do IE e solicitar a instalação do PWS. Além disso, ele está disponível no NT 4.0 Option Pack para Windows 95.
8.1.9.2. Primeiros testes
A raiz das páginas da Web do servidor PWS é unidade:\inetpub\wwwroot, onde unidade é o disco no qual você instalou o PWS. Supomos, a seguir, que essa unidade seja D. Assim, a URL http://machine/rep1/page1.html corresponderá ao arquivo d:\inetpub\wwwroot\rep1\page1.html. O servidor PWS interpreta qualquer arquivo com a extensão .asp (Active Server Pages) como um script que deve ser executado para gerar uma página HTML.
O PWS opera, por padrão, na porta 80. O servidor web Apache também... Portanto, é necessário desligar o Apache para trabalhar com o PWS caso você tenha os dois servidores. A outra solução é configurar o Apache para que ele funcione em outra porta. Assim, no arquivo de configuração do Apache, substitui-se a linha “Port 80” por “Port 81”; a partir de então, o Apache funcionará na porta 81 e poderá ser utilizado ao mesmo tempo que o PWS. Se o PWS estiver em execução e acessarmos o endereço http://localhost, obteremos uma página semelhante à seguinte:

8.1.9.3. Link PHP - PWS
- Abaixo, você encontrará um arquivo .reg destinado a modificar o Registro. Clique duas vezes nesse arquivo para modificar o Registro. Aqui, o dll necessário está localizado em d:\php4 junto com o executável do PHP. Modifique, se necessário. Os caracteres \ devem ser duplicados no caminho da DLL.
REGEDIT4
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map]
".php"="d:\\php4\\php4isapi.dll"
- Reinicie o computador para que a alteração no Registro seja aplicada.
- Crie uma pasta php no d:\inetpub\wwwroot, que é a raiz do servidor PWS. Feito isso, ative o PWS e acesse a aba “Avançado”. Selecione o botão “Adicionar” para criar uma pasta virtual:
- Confirme tudo e reinicie o PWS. Insira no d:\inetpub\wwwroot\php o arquivo intro.php, que contém apenas a seguinte linha:
- Solicite ao servidor PWS o arquivo URL http://localhost/php/intro.php. Deve ser exibida a lista de informações em PHP já apresentadas com o Apache.
8.1.10. Tomcat: servlets Java e páginas JSP (Java Server Pages)
O Tomcat é um servidor web que permite gerar páginas HTML por meio de servlets (programas Java executados pelo servidor web) ou páginas JSP (Java Server Pages), que combinam código Java e código HTML. É o equivalente às páginas ASP (Active Server Pages) do servidor IIS/PWS da Microsoft, nas quais se mistura código VBScript ou JavaScript com código HTML.
8.1.10.1. Installation
O Tomcat está disponível no endereço URL: http://jakarta.apache.org. Baixe um arquivo .exe de instalação. Ao executar esse programa, ele começa indicando qual JDK será utilizado. Na verdade, o Tomcat precisa de um JDK para se instalar e, posteriormente, compilar e executar os servlets Java. Portanto, é necessário que você tenha instalado um JDK Java antes de instalar o Tomcat. Recomenda-se o JD mais recente. A instalação criará uma estrutura de diretórios <tomcat>:

consiste simplesmente em descompactar esse arquivo em um diretório. Escolha um diretório cujo caminho contenha apenas nomes sem espaços (por exemplo, não “Program Files”), pois há um bug no processo de instalação do Tomcat. Use, por exemplo, C:\tomcat ou D:\tomcat. Vamos chamar esse diretório de <tomcat>. Nele, você encontrará uma pasta chamada jakarta-tomcat e, dentro dela, a seguinte estrutura de diretórios:
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. Inicialização/Desligamento do servidor web Tomcat
O Tomcat é um servidor Web, assim como o Apache ou o PWS. Para iniciá-lo, há links no menu de programas:
para iniciar o Tomcat | |
para desligá-lo |
Ao iniciar o Tomcat, é exibida uma janela do DOS com o seguinte conteúdo:

É possível minimizar essa janela do DOS. Ela permanecerá aberta enquanto o Tomcat estiver ativo. Em seguida, podemos passar para os primeiros testes. O servidor web Tomcat opera na porta 8080. Após iniciar o Tomcat, abra um navegador da web e acesse http://localhost:8080. Você deverá ver a seguinte página:

Siga o link “Servlet Examples”:

Clique no link Execute de RequestParameters e, em seguida, no link de Source. Você terá uma primeira visão geral do que é um servlet Java. Você poderá fazer o mesmo com os links nas páginas JSP.
Para encerrar o Tomcat, use o link “Stop Tomcat” no menu de programas.
8.1.11. JBuilder
O JBuilder é um ambiente de desenvolvimento de aplicativos Java. Para criar servlets Java sem interfaces gráficas, não é imprescindível ter esse tipo de ambiente. Um editor de texto e um JDK são suficientes. Apenas o JBuilder traz algumas vantagens a mais em relação à técnica anterior:
- facilidade de depuração: o compilador sinaliza as linhas com erros em um programa e é fácil localizar essas linhas
- sugestão de código: ao usar um objeto Java, o JBuilder exibe na linha a lista de propriedades e métodos desse objeto. Isso é muito prático, já que a maioria dos objetos Java possui inúmeras propriedades e métodos que são difíceis de memorizar.
O JBuilder pode ser encontrado no site http://www.borland.com/jbuilder. É necessário preencher um formulário para obter o software. Uma chave de ativação é enviada por e-mail. Para instalar o JBuilder 7, por exemplo, seguiu-se o seguinte procedimento:
- foram baixados três arquivos zip: para o aplicativo, para a documentação e para os exemplos. Cada um desses zip tem um link separado no site do JBuilder.
- Primeiro, instalou-se o aplicativo, depois a documentação e, por fim, os exemplos
- Ao iniciar o aplicativo pela primeira vez, é solicitada uma chave de ativação: trata-se daquela que lhe foi enviada por e-mail. Na versão 7, essa chave é, na verdade, o conteúdo completo de um arquivo de texto que pode ser colocado, por exemplo, na pasta de instalação do JB7. No momento em que a chave for solicitada, basta indicar o arquivo em questão. Feito isso, a chave não será solicitada novamente.
Há algumas configurações úteis a serem feitas caso se queira utilizar o JBuilder para criar servlets Java. De fato, a versão conhecida como “Jbuilder pessoal” é uma versão simplificada que, notavelmente, não vem com todas as classes necessárias para o desenvolvimento web em Java. É possível fazer com que o JBuilder utilize as bibliotecas de classes fornecidas pelo Tomcat. Para isso, proceda da seguinte forma:
- execute o JBuilder

- ativar a opção Tools/Configure JDKs

Na seção JDK Settings acima, normalmente aparece no campo Name um JDK 1.3.1. Se você tiver uma versão mais recente do JDK, use o botão Change para indicar o diretório de instalação dessa versão. Acima, foi especificado o diretório E:\Program Files\jdk14, onde estava instalado um JDK 1.4. A partir de agora, o JBuilder utilizará esse JDK para suas compilações e execuções. Na seção (Class, Source, Documentation), temos a lista de todas as bibliotecas de classes que serão exploradas pelo JBuilder; neste caso, as classes do JDK 1.4. As classes deste último não são suficientes para o desenvolvimento web em Java. Para adicionar outras bibliotecas de classes, usa-se o botão “Add” e indica-se os arquivos .jar adicionais que se deseja utilizar. Os arquivos .jar são bibliotecas de classes. O Tomcat 4.x traz consigo todas as bibliotecas de classes necessárias para o desenvolvimento web. Elas estão localizadas em <tomcat>\common\lib, onde <tomcat> é o diretório de instalação do Tomcat:

Com o botão “Add”, vamos adicionar essas bibliotecas, uma a uma, à lista de bibliotecas exploradas pelo JBuilder:

A partir de agora, é possível compilar programas Java em conformidade com a norma J2EE, especialmente os servlets Java. O JBuilder serve apenas para a compilação; a execução é garantida posteriormente pelo Tomcat, conforme explicado no curso.
8.2. Código-fonte dos programas
8.2.1. O cliente genérico TCP
Muitos serviços criados nos primórdios da Internet funcionam de acordo com o modelo do servidor de eco estudado anteriormente: as trocas cliente-servidor ocorrem por meio de trocas de linhas de texto. Vamos escrever um cliente TCP genérico que será iniciado da seguinte maneira: java cltTCPgenerique servidor porta
Esse cliente TCP se conectará à porta port do servidor serveur. Feito isso, ele criará duas threads:
- um thread responsável por ler os comandos digitados no teclado e enviá-los ao servidor
- um thread responsável por ler as respostas do servidor e exibi-las na tela
Por que duas threads? Cada serviço TCP-IP possui seu próprio protocolo, e às vezes ocorrem as seguintes situações:
- o cliente precisa enviar várias linhas de texto antes de receber uma resposta
- a resposta de um servidor pode conter várias linhas de texto
Portanto, o ciclo de envio de uma única linha ao servidor — recebimento de uma única linha enviada pelo servidor — nem sempre é adequado. Assim, vamos criar dois ciclos separados:
- um ciclo para ler os comandos digitados no teclado a serem enviados ao servidor. O usuário indicará o fim dos comandos com a palavra-chave fin.
- um ciclo de recepção e exibição das respostas do servidor. Esse será um ciclo infinito que só será interrompido pelo fechamento do fluxo de rede pelo servidor ou pelo usuário no teclado, ao digitar o comando fin.
Para manter esses dois loops separados, precisamos de duas threads independentes. Vejamos um exemplo de execução em que nosso cliente TCP genérico se conecta a um serviço SMTP (Protocolo de Transferência SendMail). Esse serviço é responsável pelo encaminhamento de e-mails aos seus destinatários. Ele opera na porta 25 e utiliza um protocolo de comunicação do tipo troca de linhas de texto.
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]
Vamos comentar essas trocas entre cliente e servidor:
- o serviço SMTP envia uma mensagem de boas-vindas quando um cliente se conecta a ele:
- alguns serviços possuem um comando help que fornece informações sobre os comandos que podem ser utilizados com o serviço. Neste caso, não é assim. Os comandos SMTP utilizados no exemplo são os seguintes:
- mail from: expéditeur, para indicar o endereço de e-mail do remetente da mensagem
- rcpt to: destinataire, para indicar o endereço de e-mail do destinatário da mensagem. Se houver vários destinatários, o comando rcpt to: deve ser repetido quantas vezes forem necessárias para cada um deles.
- data, que sinaliza ao servidor SMTP que a mensagem será enviada. Conforme indicado na resposta do servidor, trata-se de uma sequência de linhas terminada por uma linha contendo apenas o caractere ponto. Uma mensagem pode ter cabeçalhos separados do corpo da mensagem por uma linha em branco. Em nosso exemplo, definimos um assunto com a palavra-chave Subject:
- assim que a mensagem for enviada, é possível indicar ao servidor que terminamos com o comando quit. O servidor então encerra a conexão de rede. O thread de leitura pode detectar esse evento e ser encerrado.
- O usuário então digita “fin” no teclado para interromper também o thread de leitura dos comandos digitados no teclado.
Se verificarmos o e-mail recebido, temos o seguinte (Outlook):

Observe-se que o serviço SMTP não consegue detectar se um remetente é válido ou não. Portanto, nunca se pode confiar no campo from de uma mensagem. Neste caso, o remetente machin@univ-angers.fr não existia.
Esse cliente TCP genérico pode nos permitir descobrir o protocolo de comunicação dos serviços da Internet e, a partir daí, criar classes especializadas para clientes desses serviços. Vamos descobrir o protocolo de comunicação do serviço POP (Post Office Protocol), que permite recuperar e-mails armazenados em um servidor. Ele opera na porta 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]
Os principais comandos são os seguintes:
- user login, onde se insere o nome de usuário na máquina que hospeda nossos e-mails
- pass password, onde se insere a senha associada ao login anterior
- list, para obter a lista de mensagens no formato número, tamanho em bytes
- retr i, para ler a mensagem nº i
- quit, para encerrar a sessão.
Vamos agora conhecer o protocolo de comunicação entre um cliente e um servidor Web, que normalmente opera na porta 80:
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]
Um cliente web envia seus comandos ao servidor de acordo com o seguinte esquema:
Somente após receber a linha vazia é que o servidor web responde. No exemplo, utilizamos apenas um comando:
que solicita ao servidor o URL /index.html e indica que está trabalhando com o protocolo HTTP versão 1.0. A versão mais recente desse protocolo é a 1.1. O exemplo mostra que o servidor respondeu enviando o conteúdo do arquivo index.html e, em seguida, encerrou a conexão, já que é possível observar que o thread de leitura das respostas foi encerrado. Antes de enviar o conteúdo do arquivo index.html, o servidor web enviou uma série de cabeçalhos encerrada por uma linha vazia:
<-- 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>
A linha <html> é a primeira linha do arquivo /index.html. O que vem antes são chamados de cabeçalhos HTTP (Protocolo de Transferência HyperText). Não vamos detalhar esses cabeçalhos aqui, mas vale lembrar que nosso cliente genérico permite acessá-los, o que pode ser útil para compreendê-los. A primeira linha, por exemplo:
indica que o servidor web contatado compreende o protocolo HTTP/1.1 e que encontrou o arquivo solicitado (200 OK), sendo 200 um código de resposta HTTP. As linhas
informam ao cliente que ele receberá 11.251 bytes representando o texto HTML (HyperText Markup Language) e que, ao final do envio, a conexão será encerrada.
Portanto, temos aqui um cliente TCP muito prático. Ele certamente faz menos do que o programa oficial telnet, mas foi interessante escrevê-lo nós mesmos. O código do cliente TCP genérico é o seguinte:
// pacotes importados
import java.io.*;
import java.net.*;
public class clientTCPgenerique{
// recebe como parâmetro as características de um serviço na forma
// servidor e porta
// conecta-se ao serviço
// cria um thread para ler comandos digitados no teclado
// esses comandos serão enviados ao servidor
// cria um thread para ler as respostas do servidor
// estas serão exibidas na tela
// tudo termina com o comando “fin” digitado no teclado
// variável de instância
private static Socket client;
public static void main(String[] args){
// sintaxe
final String syntaxe="pg serveur port";
// número de argumentos
if(args.length != 2)
erreur(syntaxe,1);
// anota-se o nome do servidor
String serveur=args[0];
// a porta deve ser um número inteiro maior que 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;
// podem ocorrer problemas
try{
// conectamos-nos ao serviço
client=new Socket(serveur,port);
}catch(Exception ex){
// erro
erreur("Impossible de se connecter au service ("+ serveur
+","+port+"), erreur : "+ex.getMessage(),3);
// fim
return;
}//catch
// criando os threads de leitura/gravação
new ClientSend(client).start();
new ClientReceive(client).start();
// fim do thread principal
return;
}// main
// exibição de erros
public static void erreur(String msg, int exitCode){
// exibição de erro
System.err.println(msg);
// encerramento com erro
System.exit(exitCode);
}//erro
}//classe
class ClientSend extends Thread {
// classe responsável por ler comandos digitados no teclado
// e enviá-los a um servidor por meio de um cliente TCP passado como parâmetro
private Socket client; // o cliente TCP
// construtor
public ClientSend(Socket client){
// observa-se o cliente TCP
this.client=client;
}//construtor
// método Run da thread
public void run(){
// dados locais
PrintWriter OUT=null; // fluxo de gravação de rede
BufferedReader IN=null; // fluxo do teclado
String commande=null; // comando lido no teclado
// gerenciamento de erros
try{
// criação do fluxo de gravação de rede
OUT=new PrintWriter(client.getOutputStream(),true);
// criação do fluxo de entrada do teclado
IN=new BufferedReader(new InputStreamReader(System.in));
// ciclo de entrada e envio de comandos
System.out.println("Commandes : ");
while(true){
// leitura do comando digitado no teclado
commande=IN.readLine().trim();
// Concluído?
if (commande.toLowerCase().equals("fin")) break;
// envio do comando ao servidor
OUT.println(commande);
// próximo comando
}//while
}catch(Exception ex){
// erro
System.err.println("Envoi : L'erreur suivante s'est produite : " + ex.getMessage());
}//catch
// fim — fechamento dos fluxos
try{
OUT.close();client.close();
}catch(Exception ex){}
// sinaliza-se o fim do thread
System.out.println("[Envoi : fin du thread d'envoi des commandes au serveur]");
}//execução
}//classe
class ClientReceive extends Thread{
// classe responsável por ler as linhas de texto destinadas a um
// cliente TCP passado como parâmetro
private Socket client; // o cliente TCP
// construtor
public ClientReceive(Socket client){
// registra-se o cliente TCP
this.client=client;
}//construtor
// método Run da thread
public void run(){
// dados locais
BufferedReader IN=null; // fluxo de leitura de rede
String réponse=null; // resposta do servidor
// gestão de erros
try{
// criação do fluxo de leitura de rede
IN=new BufferedReader(new InputStreamReader(client.getInputStream()));
// ciclo de leitura das linhas de texto do fluxo IN
while(true){
// leitura do fluxo de rede
réponse=IN.readLine();
// fluxo encerrado?
if(réponse==null) break;
// exibição
System.out.println("<-- "+réponse);
}//while
}catch(Exception ex){
// erro
System.err.println("Réception : L'erreur suivante s'est produite : " + ex.getMessage());
}//catch
// fim — fechando os fluxos
try{
IN.close();client.close();
}catch(Exception ex){}
// notifica-se o fim do thread
System.out.println("[Réception : fin du thread de lecture des réponses du serveur]");
}//execução
}//classe
8.2.2. O servidor TCP genérico
Agora vamos nos concentrar em um servidor
- que exibe na tela os comandos enviados por seus clientes
- e lhes envia, como resposta, as linhas de texto digitadas no teclado por um usuário. Portanto, é o próprio usuário que atua como servidor.
O programa é executado por: java serveurTCPgenerique portEcoute, onde portEcoute é a porta à qual os clientes devem se conectar. O atendimento ao cliente será garantido por duas threads:
- um thread dedicado exclusivamente à leitura das linhas de texto enviadas pelo cliente
- um thread dedicado exclusivamente à leitura das respostas digitadas pelo usuário. Este sinalizará, por meio do comando fin, que está encerrando a conexão com o cliente.
O servidor cria duas threads por cliente. Se houver n clientes, haverá 2n threads ativas ao mesmo tempo. O servidor, por sua vez, nunca é encerrado, a menos que o usuário pressione Ctrl-C no teclado. Vejamos alguns exemplos.
O servidor é iniciado na porta 100 e usamos o cliente genérico para nos comunicarmos com ele. A janela do cliente é a seguinte:
E:\data\serge\MSNET\c#\rede\cliente tcp genérico> 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]
As linhas que começam com <-- são as enviadas do servidor para o cliente; as demais, do cliente para o servidor. A janela do servidor é a seguinte:
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]
As linhas que começam com <-- são aquelas enviadas do cliente para o servidor. As linhas N: são as linhas enviadas do servidor para o cliente nº N. O servidor acima ainda está ativo, enquanto o cliente 1 já foi encerrado. Iniciamos um segundo cliente para o mesmo servidor:
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]
A janela do servidor fica assim:
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
Vamos agora simular um servidor web, iniciando nosso servidor genérico na porta 88:
Dos> java serveurTCPgenerique 88
Serveur générique lancé sur le port 88
Agora, vamos abrir um navegador e acessar a página http://localhost:88/exemple.html. O navegador se conectará à porta 88 da máquina localhost e, em seguida, solicitará a página /exemple.html:

Vamos agora observar a janela do nosso servidor:
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
<--
Assim, identificamos os cabeçalhos HTTP enviados pelo navegador. Isso nos permite descobrir, aos poucos, o protocolo HTTP. Em um exemplo anterior, criamos um cliente web que enviava apenas o comando GET. Isso já havia sido suficiente. Vemos aqui que o navegador envia outras informações ao servidor. Elas têm como objetivo indicar ao servidor que tipo de cliente ele tem diante de si. Vemos também que os cabeçalhos HTTP terminam com uma linha em branco.
Vamos elaborar uma resposta para o nosso cliente. O usuário no teclado é, neste caso, o verdadeiro servidor e pode elaborar uma resposta manualmente. Lembremo-nos da resposta fornecida por um servidor web em um exemplo anterior:
<-- 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>
Vamos tentar dar uma resposta semelhante:
...
<-- 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]
As linhas que começam com 2: são enviadas do servidor para o cliente nº 2. O comando fin encerra a conexão do servidor com o cliente. Limitamos nossa resposta aos seguintes cabeçalhos HTTP:
HTTP/1.1 200 OK
2 : Server: serveur tcp generique
2 : Connection: close
2 : Content-Type: text/html
2 :
Não informamos o tamanho do arquivo que vamos enviar (Content-Length), mas nos limitamos a indicar que vamos encerrar a conexão (Connection: close) após o envio do mesmo. Isso é suficiente para o navegador. Ao perceber que a conexão foi encerrada, ele saberá que a resposta do servidor foi concluída e exibirá a página HTML que lhe foi enviada. Esta página é a seguinte:
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>
Em seguida, o usuário encerra a conexão com o cliente digitando o comando fin. O navegador reconhece então que a resposta do servidor foi concluída e pode exibi-la:

Se, no exemplo acima, digitarmos View/Source para ver o que o navegador recebeu, obtemos:

ou seja, exatamente o que foi enviado a partir do servidor genérico.
O código do servidor TCP genérico é o seguinte:
// pacotes
import java.io.*;
import java.net.*;
public class serveurTCPgenerique{
// programa principal
public static void main (String[] args){
// recebe as solicitações dos clientes na porta de escuta
// cria um thread para ler as solicitações do cliente
// estas serão exibidas na tela
// cria um thread para ler os comandos digitados no teclado
// esses comandos serão enviados como resposta ao cliente
// tudo termina com o comando “fin” digitado no teclado
final String syntaxe="Syntaxe : pg port";
// variável de instância
// existe algum argumento
if(args.length != 1)
erreur(syntaxe,1);
// a porta deve ser um número inteiro >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);
// criamos o serviço de escuta
ServerSocket ecoute=null;
int nbClients=0; // número de clientes atendidos
try{
// criamos o serviço
ecoute=new ServerSocket(port);
// acompanhamento
System.out.println("Serveur générique lancé sur le port " + port);
// ciclo de atendimento aos clientes
Socket client=null;
while (true){ // loop infinito — será interrompido com Ctrl-C
// aguardando um cliente
client=ecoute.accept();
// o serviço é executado em threads separadas
nbClients++;
// são criadas as threads de leitura/gravação
new ServeurSend(client,nbClients).start();
new ServeurReceive(client,nbClients).start();
// retornamos à escuta de solicitações
}// fim do while
}catch(Exception ex){
// se sinaliza o erro
erreur("L'erreur suivante s'est produite : " + ex.getMessage(),3);
}//catch
}// fim de main
// exibição dos erros
public static void erreur(String msg, int exitCode){
// exibição do erro
System.err.println(msg);
// parada com erro
System.exit(exitCode);
}//erro
}//classe
class ServeurSend extends Thread{
// classe responsável por ler respostas digitadas no teclado
// e enviá-las a um cliente por meio de um cliente TCP passado ao construtor
Socket client; // o cliente TCP
int numClient; // nº do cliente
// construtor
public ServeurSend(Socket client, int numClient){
// observa-se o cliente TCP
this.client=client;
// e seu número
this.numClient=numClient;
}//fabricante
// método Run da thread
public void run(){
// dados locais
PrintWriter OUT=null; // fluxo de gravação de rede
String réponse=null; // resposta lida no teclado
BufferedReader IN=null; // fluxo do teclado
// acompanhamento
System.out.println("Thread de lecture des réponses du serveur au client "+ numClient + " lancé");
// gerenciamento de erros
try{
// criação do fluxo de gravação de rede
OUT=new PrintWriter(client.getOutputStream(),true);
// criação do fluxo do teclado
IN=new BufferedReader(new InputStreamReader(System.in));
// ciclo de entrada e envio de comandos
while(true){
// identificação do cliente
System.out.print("--> " + numClient + " : ");
// Leitura da resposta digitada no teclado
réponse=IN.readLine().trim();
// Concluído?
if (réponse.toLowerCase().equals("fin")) break;
// envio da resposta ao servidor
OUT.println(réponse);
// próxima resposta
}//enquanto
}catch(Exception ex){
// erro
System.err.println("L'erreur suivante s'est produite : " + ex.getMessage());
}//catch
// fim — fechamento dos fluxos
try{
OUT.close();client.close();
}catch(Exception ex){}
// sinaliza-se o fim do thread
System.out.println("[fin du Thread de lecture des réponses du serveur au client "+ numClient+ "]");
}//execução
}//classe
class ServeurReceive extends Thread{
// classe responsável por ler as linhas de texto enviadas ao servidor
// por meio de um cliente TCP passado ao construtor
Socket client; // o cliente TCP
int numClient; // nº do cliente
// construtor
public ServeurReceive(Socket client, int numClient){
// observa-se o cliente TCP
this.client=client;
// e seu número
this.numClient=numClient;
}//fabricante
// método Run da thread
public void run(){
// dados locais
BufferedReader IN=null; // fluxo de leitura de rede
String réponse=null; // resposta do servidor
// acompanhamento
System.out.println("Thread de lecture des demandes du client "+ numClient + " lancé");
// gerenciamento de erros
try{
// criação do fluxo de leitura de rede
IN=new BufferedReader(new InputStreamReader(client.getInputStream()));
// ciclo de leitura das linhas de texto do fluxo IN
while(true){
// leitura do fluxo de rede
réponse=IN.readLine();
// fluxo encerrado?
if(réponse==null) break;
// exibição
System.out.println("<-- "+réponse);
}//while
}catch(Exception ex){
// erro
System.err.println("L'erreur suivante s'est produite : " + ex.getMessage());
}//catch
// fim — fechando os fluxos
try{
IN.close();client.close();
}catch(Exception ex){}
// notifica-se o fim do thread
System.out.println("[fin du Thread de lecture des demandes du client "+ numClient+"]");
}//execução
}//classe
8.3. JAVASCRIPT
Nesta seção, apresentamos três exemplos de uso do JavaScript nas páginas WEB. Nosso foco é o gerenciamento de formulários, mas o JavaScript pode fazer muito mais do que isso.
8.3.1. Recuperar as informações de um formulário
O exemplo abaixo mostra como recuperar, no navegador, os dados inseridos pelo usuário em um formulário. Isso geralmente permite realizar um pré-processamento antes de enviá-los ao servidor.
8.3.1.1. O formulário
Temos um formulário que reúne os componentes mais comuns e um botão “Exibir”, que permite visualizar as entradas feitas pelo usuário.

8.3.1.2. O código
<html>
<head>
<title>Un formulaire traité par Javascript</title>
<script language="javascript">
function afficher(){
// exibe em uma lista as informações do formulário
// primeiro se apaga
effacerInfos();
// exibe o valor dos # campos
with(document.frmExemple){
// campo oculto
ecrire("champ caché="+cache.value);
// campo de texto simples
ecrire("champ textuel simple="+simple.value);
// campo de texto múltiplo
ecrire("champ textuel multiple="+lignes.value);
// botões de opção
for(i=0;i<radio.length;i++){
texte="radio["+i+"]="+radio[i].value;
if(radio[i].checked) texte+=", coché";
ecrire(texte);
}//for
// caixas de seleção
for(i=0;i<qcm.length;i++){
texte="qcm["+i+"]="+qcm[i].value;
if(qcm[i].checked) texte+=", coché";
ecrire(texte);
}//for
//lista suspensa
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);
}//para
//lista de múltiplas opções
for(i=0;i<lstVoitures.length;i++){
texte="lstVoitures["+i+"]="+lstVoitures.options[i].text;
if(lstVoitures.options[i].selected) texte+=",sélectionné";
ecrire(texte);
}//para
//senha
ecrire("mot de passe="+passwd.value);
}//com
}//função
function ecrire(texte){
// escreve texto na lista de informações
frmInfos.lstInfos.options[frmInfos.lstInfos.length]=new Option(texte);
}//gravar
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. Expressões regulares em JavaScript
No navegador, o JavaScript pode ser usado para verificar a validade dos dados inseridos pelo usuário antes de enviá-los ao servidor. Aqui está um programa para testar essas expressões regulares.
8.3.2.1. A página de teste

8.3.2.2. O código da página
<html>
<head>
<title>Les expressions régulières en Javascript</title>
<script language="javascript">
function afficherInfos(){
with(document.frmRegExp){
// tem algo a ser feito?
if (! verifier()) return;
// tudo certo — apagamos os resultados anteriores
effacerInfos();
// verificação do modelo
modele=new RegExp(txtModele.value);
champs=modele.exec(txtChaine.value);
if(champs==null)
// sem correspondência entre o modelo e a sequência
ecrireInfos("pas de correspondance");
else{
// correspondência — exibindo os resultados obtidos
ecrireInfos("Il y a correspondance");
for(i=0;i<champs.length;i++)
ecrireInfos("champs["+i+"]=["+champs[i]+"]");
}//caso contrário
}//com
}//função
function ecrireInfos(texte){
// grava texto na lista de informações
document.frmRegExp.lstInfos.options[document.frmRegExp.lstInfos.length]=new Option(texte);
}//gravar
function effacerInfos(){
frmRegExp.lstInfos.length=0;
}//effacerInfos
function jouer(){
// verifica se o modelo corresponde à sequência do exemplo selecionado
with(document.frmRegExp){
txtModele.value=lstModeles.options[lstModeles.selectedIndex].text
txtChaine.value=lstChaines.options[lstChaines.selectedIndex].text
afficherInfos();
}//com
}//executar
function ajouter(){
//adiciona o teste atual aos exemplos
with(document.frmRegExp){
// há algo a ser feito?
if (! verifier()) return;
// adição
lstModeles.options[lstModeles.length]=new Option(txtModele.value);
lstChaines.options[lstChaines.length]=new Option(txtChaine.value);
// limpar entradas
txtModele.value="";
txtChaine.value="";
}//com
}//adicionar
function verifier(){
// verifica se os campos de entrada estão preenchidos
with(document.frmRegExp){
champs=/^\s*$/.exec(txtModele.value);
if(champs!=null){
alert("Vous n'avez pas indiqué de modèle");
txtModele.focus();
return false;
}//se
champs=/^\s*$/.exec(txtChaine.value);
if(champs!=null){
alert("Vous n'avez pas indiqué de chaîne de test");
txtChaine.focus();
return false;
}//se
// tudo certo
return true;
}//com
}//verificar
</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. Gerenciamento de listas em JavaScript
8.3.3.1. O formulário

8.3.3.2. O código
<html>
<head>
<title>Les listes en Javascript</title>
<script language="javascript">
// adicionar
function ajouter(L1,L2,T){
// adiciona o valor do campo T às listas L1, L2
// há algo a ser feito?
champs=/^\s*$/.exec(T.value);
if(champs!=null){
// o campo está vazio
alert("Vous n'avez pas indiqué la valeur à ajouter");
txtElement.focus();
return;
}//if
// adiciona-se o elemento
L1.options[L1.length]=new Option(T.value);
L2.options[L2.length]=new Option(T.value);
T.value="";
}//adicionar
//esvaziar
function vider(L){
// esvazia a lista L
L.length=0;
}//esvaziar
//transferir
function transfert(L1,L2,simple){
//transfere para L2 os elementos selecionados na lista L1
// há algo a ser feito?
// índice do elemento selecionado em L1
index1=L1.selectedIndex;
if(index1==-1){
alert("Vous n'avez pas sélectionné d'élément");
return;
}//se
// qual é o modo de seleção dos elementos das listas
if(simple){ // seleção simples
element1=L1.options[index1].text;
//adição em L2
L2.options[L2.length]=new Option(element1);
//exclusão em L1
L1.options[index1]=null;
}//simples
if(! simple){ //seleção múltipla
//percorrer a lista 1 na ordem inversa
for(i=L1.length-1;i>=0;i--){
//elemento selecionado?
if(L1.options[i].selected){
//adiciona-se a L2
L2.options[L2.length]=new Option(L1.options[i].text);
//é removido de L1
L1.options[i]=null;
}//se
}//para i
}//if ! simples
}//transferência
</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>


