Skip to content

8. Ekler

8.1. Web geliştirme araçları

Burada, web geliştirme için gerekli araçların nereden bulunabileceğini ve nasıl kurulacağını açıklıyoruz. Bazı araçların sürümleri güncellenmiştir ve burada verilen açıklamalar en yeni sürümler için artık geçerli olmayabilir. Bu durumda okuyucunun duruma uyum sağlaması gerekecektir... Web programlama dersinde, esas olarak aşağıdaki araçları kullanacağız; bunların tümü ücretsiz olarak mevcuttur:

  • XML formatını görüntüleyebilen güncel bir tarayıcı. Ders örnekleri Internet Explorer 6 ile test edilmiştir.
  • güncel bir JDK (Java Development Kit). Ders örnekleri, JDK 1.4 ile test edilmiştir. Bu JDK, tarayıcılar için Java 1.4 eklentisini beraberinde getirir; bu sayede tarayıcılar, JDK 1.4'ü kullanan Java uygulamalarını görüntüleyebilir.
  • Java servlet'leri yazmak için bir Java geliştirme ortamı. Burada söz konusu olan JBuilder 7'dir.
  • web sunucuları: Apache, PWS (Kişisel Web Sunucusu), Tomcat.
    • Apache, PERL (Practical Extracting and Reporting Language) veya PHP (Personal Home Page) ile web uygulamaları geliştirmek için kullanılacaktır.
    • PWS, ASP (Active Server Pages) veya PHP dillerinde web uygulamaları geliştirmek için kullanılacaktır.
    • Tomcat, Java servletleri veya JSP (Java Server Pages) sayfaları kullanılarak web uygulamaları geliştirmek için kullanılacaktır
  • bir veritabanı yönetim uygulaması: MySQL
  • EasyPHP: Apache web sunucusunu, PHP dilini ve SGBD MySQL'i bir araya getiren bir araç

8.1.1. Web Sunucuları, Tarayıcılar, Komut Dosyası Dilleri

  1. Başlıca Web Sunucuları
    • Apache (Linux, Windows)
    • Internet Information Server IIS (NT), Personal Web Server PWS (Windows 9x)
  1. Başlıca tarayıcılar
    • Internet Explorer (Windows)
    • Netscape (Linux, Windows)
  1. Sunucu tarafı betik dilleri
    • VBScript (IIS, PWS)
    • JavaScript (IIS, PWS)
    • Perl (Apache, IIS, PWS)
    • PHP (Apache, IIS, PWS)
    • Java (Apache, Tomcat)
    • Diller .NET
  1. Tarayıcı tarafında çalışan betik dilleri
    • VBScript (IE)
    • Javascript (IE, Netscape)
    • PerlScript (IE)
    • Java (IE, Netscape)

8.1.2. Araçları nerede bulabilirim?

Netscape
http://www.netscape.com/ (indirme bağlantısı)
Internet Explorer
http://www.microsoft.com/windows/ie/default.asp
PHP
http://www.php.net
http://www.php.net/downloads.php (Windows İkili Dosyaları)
PERL
http://www.activestate.com http://www.activestate.com/Products/
http://www.activestate.com/Products/ActivePerl/
Vbscript, Javascript
http://msdn.microsoft.com/scripting (Windows Script bağlantısını takip edin)
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
NT 4.0 Option pack for Windows 95
Windows 98 için CD paketinde yer alır
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

Bu uygulama, aynı pakette aşağıdakileri bir araya getirmesi açısından oldukça kullanışlıdır:

  • Apache web sunucusu (1.3.x)
  • PHP dili (4.x)
  • SGBD MySQL (3.23.x)
  • MySQL yönetim aracı: PhpMyAdmin

Kurulum uygulaması şu şekilde görünür:

Image

EasyPHP'in kurulumu sorunsuz gerçekleşir ve dosya sisteminde bir dizin yapısı oluşturulur:

Image

easyphp.exe
uygulamanın yürütülebilir dosyası
apache
Apache sunucusunun dizin yapısı
mysql
SGBD MySQL dizin yapısı
phpmyadmin
phpMyAdmin uygulamasının dizin yapısı
php
php dizin yapısı
www
EasyPHP Apache sunucusu tarafından sunulan web sayfalarının dizin yapısının kökü
cgi-bin
Apache sunucusu için CGI komut dosyalarını yerleştirebileceğiniz dizin yapısı

EasyPHP'in en önemli avantajı, uygulamanın önceden yapılandırılmış olarak gelmesidir. Böylece Apache, PHP ve MySQL, birbirleriyle uyumlu çalışacak şekilde önceden yapılandırılmıştır. Programlar menüsündeki bağlantısı üzerinden EasyPhp çalıştırıldığında, ekranın sağ alt köşesinde bir simge belirir.

Apache web sunucusu ve MySQL veritabanı çalışır durumdaysa, kırmızı noktalı E harfi yanıp sönmelidir. Bu simgeye farenin sağ tuşuyla tıklandığında, aşağıdaki menü seçeneklerine erişilir:

Image

Administration seçeneği, ayarlamalar yapmanıza ve çalışıp çalışmadığını test etmenize olanak tanır:

Image

8.1.3.1. Yönetim PHP

"php bilgileri" düğmesi, Apache-PHP ikilisinin düzgün çalışıp çalışmadığını kontrol etmenizi sağlar: PHP adlı bir bilgi sayfası görünmelidir:

Image

"Eklentiler" düğmesi, PHP için yüklü olan eklentilerin listesini gösterir. Bunlar aslında işlev kütüphaneleridir.

Image

Yukarıdaki ekran örneğinde, MySQL veritabanını kullanmak için gerekli işlevlerin mevcut olduğu görülmektedir.

Ayarlar düğmesi, login/motdepasse veritabanı yöneticisinin MySQL bilgilerini gösterir.

Image

MySQL veritabanının kullanımı bu kısa tanıtımın kapsamını aşmaktadır, ancak burada veritabanı yöneticisi için bir şifre belirlenmesi gerektiği açıktır.

8.1.3.2. Apache Yönetimi

Yine EasyPHP yönetim sayfasında, “takma adlarınız” bağlantısı, bir dizine bağlı takma adlar tanımlamanıza olanak tanır. Bu, web sayfalarını easyPhp dizin yapısındaki www dizini dışındaki yerlere yerleştirmenizi sağlar.

Image

Yukarıdaki sayfaya aşağıdaki bilgileri girersek:

Image

ve valider düğmesini kullanırsak, <easyphp>\apache\conf\httpd.conf dosyasına aşağıdaki satırlar eklenir:

    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>, EasyPHP'in kurulum dizinini belirtir. httpd.conf ise Apache sunucusunun yapılandırma dosyasıdır. Dolayısıyla, bu dosyayı doğrudan düzenleyerek de aynı işlemi gerçekleştirebilirsiniz. httpd.conf dosyasında yapılan bir değişiklik normalde Apache tarafından hemen dikkate alınır. Aksi takdirde, Apache'yi durdurup easyphp simgesini kullanarak yeniden başlatmanız gerekir:

Image

Örneğimizi tamamlamak için, artık e:\data\serge\web dizin yapısına web sayfaları yerleştirebiliriz:

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

14/07/2002  17:02                3 767 balises.htm

ve st takma adını kullanarak bu sayfayı çağırabiliriz:

Image

Bu örnekte, Apache sunucusu 81 numaralı bağlantı noktasında çalışacak şekilde yapılandırılmıştır. Varsayılan bağlantı noktası 80'dir. Bu ayar, daha önce karşılaştığımız httpd.conf dosyasındaki aşağıdaki satırla kontrol edilir:

Port 81

8.1.3.3. Apache yapılandırma dosyası htpd.conf

Apache'yi biraz daha ayrıntılı bir şekilde yapılandırmak istediğimizde, <easyphp>\apache\conf klasöründe bulunan httpd.conf yapılandırma dosyasını "elle" değiştirmek zorundayız:

Image

Bu yapılandırma dosyasıyla ilgili dikkat edilmesi gereken bazı noktalar şunlardır:

ligne(s)
rol
ServerRoot "D:/Program Files/Apache Group/Apache"
Apache dizin yapısının bulunduğu klasörü gösterir
Port 80
Web sunucusunun hangi bağlantı noktasında çalışacağını belirtir. Genellikle bu değer 80'dir. Bu satırı değiştirerek, web sunucusunun başka bir bağlantı noktasında çalışmasını sağlayabilirsiniz
ServerAdmin root@istia.univ-angers.fr
Apache sunucusunun yöneticisinin e-posta adresi
ServerName stahe.istia.uang
Apache sunucusunun "çalıştığı" makinenin adı
ServerRoot "E:/Program Files/EasyPHP/apache"
Apache sunucusunun kurulum dizini. Yapılandırma dosyasında göreceli dosya adları geçtiğinde, bunlar bu dizine göre görelidir.
DocumentRoot "E:/Program Files/EasyPHP/www"
sunucu tarafından sunulan web sayfalarının dizin yapısının kök klasörü. Burada, http://machine/rep1/fic1.html URL'si E:\Program Files\EasyPHP\www\rep1\fic1.html dosyasına karşılık gelir
<Directory "E:/Program Files/EasyPHP/www">
önceki klasörün özelliklerini belirler
ErrorLog logs/error.log
günlük dosyası klasörü, yani aslında <ServerRoot>\logs\error.log : E:\Program Files\EasyPHP\apache\logs\error.log. Apache sunucusunun çalışmadığını fark ederseniz, bu dosyayı kontrol etmelisiniz.
    ScriptAlias /cgi-bin/ "E:/Program Files/EasyPHP/cgi-bin/"
E:\Program Files\EasyPHP\cgi-bin, CGI komut dosyalarını yerleştirebileceğiniz dizin yapısının kök dizinidir. Böylece, URL http://machine/cgi-bin/rep1/script1.pl, CGI E:\Program Files\EasyPHP\cgi-bin\rep1\script1.pl komut dosyasının URL'si olacaktır.
<Directory "E:/Program Files/EasyPHP/cgi-bin/">
yukarıdaki klasörün özelliklerini belirler
LoadModule php4_module "E:/Program
 Files/EasyPHP/php/php4apache.dll"
AddModule mod_php4.c
Apache'nin PHP4 ile çalışmasını sağlayan modül yükleme satırları.
    AddType application/x-httpd-php
 .phtml .pwml .php3 
.php4 .php .php2 .inc
PHP tarafından işlenmesi gereken dosyalar olarak kabul edilecek dosya soneklerini belirler

8.1.3.4. MySQL'in PhpMyAdmin ile yönetimi

EasyPhp yönetim sayfasında, PhpMyAdmin düğmesine tıklayın:

Image

Accueil altındaki açılır liste,
görüntülenebilir.
Parantez içindeki sayı, tablo sayısını gösterir. Bir
bir veritabanı seçildiğinde, içindeki tablolar görüntülenir:

Web sayfası, veritabanı üzerinde bir dizi işlem sunmaktadır:

Image

user'teki Afficher bağlantısına tıklandığında:

Image

Burada tek bir kullanıcı vardır: root, ki bu da MySQL'in yöneticisidir. Modifier bağlantısını takip ederek, şu anda boş olan şifresini değiştirebiliriz; ancak bu, bir yönetici için tavsiye edilmez.

Zengin özelliklere sahip ve birkaç sayfa boyunca ele alınmayı hak eden PhpMyAdmin hakkında daha fazla ayrıntıya girmeyeceğiz.

8.1.4. PHP

PHP'i EasyPhp uygulaması aracılığıyla nasıl elde edeceğimizi gördük. PHP'i doğrudan elde etmek için http://www.php.net sitesine gidin.

PHP sadece web ortamında kullanılmaz. Windows'ta bir komut dosyası dili olarak da kullanılabilir. Aşağıdaki komut dosyasını oluşturun ve date.php adıyla kaydedin:

<?
   // saati gösteren PHP betiği
  $maintenant=date("j/m/y, H:i:s",time());
  echo "Nous sommes le $maintenant";
?>

DOS penceresinde, date.php dizinine gidin ve dosyayı çalıştırın:

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

Internet Explorer'ın önceden yüklenmiş olması tercih edilir. Eğer yüklüyse, Active Perl onu, PERL sayfalarındaki HTML komut dosyalarını kabul edecek şekilde yapılandıracaktır; bu komut dosyaları, IE tarafından istemci tarafında çalıştırılacaktır. Active Perl'in web sitesi URL http://www.activestate.comA adresindedir. Kurulum sırasında, PERL, <perl> adını vereceğimiz bir dizine kurulacaktır. Bu dizin aşağıdaki dizin yapısını içerir:

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

perl.exe yürütülebilir dosyası <perl>\bin dizininde bulunmaktadır. Perl, Windows ve Unix işletim sistemlerinde çalışan bir betik dilidir. Ayrıca WEB programlamasında da kullanılır. İlk betiğimizi yazalım:

# saati gösteren PERL betiği

# modüller
use strict;

# program
my ($secondes,$minutes,$heure)=localtime(time);
print "Il est $heure:$minutes:$secondes\n";

Bu komut dosyasını heure.pl adıyla bir dosyaya kaydedin. Bir DOS penceresi açın, önceki komut dosyasının bulunduğu dizine gidin ve komut dosyasını çalıştırın:

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

8.1.6. Vbscript, Javascript, Perlscript

Bu diller, Windows için komut dosyası dilleridir. Özellikle Windows altında doğrudan kullanım için, örneğin sistem yönetimi komut dosyaları yazmak amacıyla

  • Windows Scripting Host gibi çeşitli ortamlarda çalışabilirler; özellikle Windows altında doğrudan kullanım için, örneğin
  • Internet Explorer. Bu durumda, HTML sayfalarında kullanılır ve bu sayfalara, yalnızca HTML diliyle elde edilemeyen bir etkileşim özelliği kazandırır.
  • Internet Information Server (IIS), NT/2000 üzerinde çalışan Microsoft'un web sunucusu ve Win9x üzerinde çalışan eşdeğeri Personal Web Server (PWS). Bu durumda, web sunucusu tarafında programlama yapmak için vbscript kullanılır; bu teknolojiye Microsoft tarafından ASP (Active Server Pages) adı verilmiştir.

Kurulum dosyasını URL adresinden indirin: http://msdn.microsoft.com/scripting ve Windows Script bağlantılarını takip edin. Kurulan bileşenler:

  • Windows Scripting Host konteyneri; bu konteyner, Vbscript ve Javascript gibi çeşitli betik dillerinin yanı sıra Active Perl ile birlikte gelen PerlScript gibi diğer dillerin de kullanılmasını sağlar.
  • bir VBscript yorumlayıcısı
  • bir Javascript yorumlayıcısı

Şimdi birkaç hızlı test yapalım. Aşağıdaki vbscript programını oluşturalım:

' bir sınıf
class personne
  Dim nom
  Dim age
End class

' kişi nesnesinin oluşturulması
Set p1=new personne
With p1
  .nom="dupont"
  .age=18
End With

' p1 kişisinin özelliklerini görüntüleme
With p1
  wscript.echo "nom=" & .nom
  wscript.echo "age=" & .age
End With

Bu program nesneler kullanır. Adını objets.vbs olarak belirleyelim (vbs uzantısı bir vbscript dosyasını belirtir). Programın bulunduğu dizine gidelim ve programı çalıştıralım:

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

Şimdi, dizileri kullanan aşağıdaki JavaScript programını yazalım:

// bir varyant içindeki dizi
// boş dizi
tableau=new Array();
affiche(tableau);
// dinamik olarak büyüyen dizi
for(i=0;i<3;i++){
  tableau.push(i*10);
}
// tablonun görüntülenmesi
affiche(tableau);
// yine
for(i=3;i<6;i++){
  tableau.push(i*10);
}
affiche(tableau);

// çok boyutlu tablolar
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);

// son
WScript.quit(0);

// ---------------------------------------------------------
function affiche(tableau){
  // tablo görüntüleme
  for(i=0;i<tableau.length;i++){
    WScript.echo("tableau[" + i + "]=" + tableau[i]);
  }//for
}//işlevi

// ---------------------------------------------------------
function affiche2(tableau){
   // tablo görüntüsü
  for(i=0;i<tableau.length;i++){
    for(j=0;j<tableau[i].length;j++){
      WScript.echo("tableau[" + i + "," + j + "]=" + tableau[i][j]);
    }// j için
  }//i için
}//işlev

Bu program tablolar kullanır. Adını tableaux.js olarak belirleyelim (js son eki, bir javascript dosyasını belirtir). Programın bulunduğu dizine gidelim ve programı çalıştıralım:

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

Son olarak, Perlscript ile bir örnek daha verelim. Perlscript'e erişebilmek için Active Perl'in kurulu olması gerekir.

<job id="PERL1">
  <script language="PerlScript">
       # klasik Perl
    %dico=("maurice"=>"juliette","philippe"=>"marianne");
    @cles= keys %dico;
    for ($i=0;$i<=$#anahtarlar;$i++){
        $cle=$cles[$i];
      $valeur=$dico{$cle};
        $WScript->echo ("clé=".$cle.", valeur=".$valeur);
    }
     # Windows Script nesnelerini kullanan Perl betiği
    $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>

Bu program, iki sözlüğün oluşturulmasını ve kullanımını gösterir: biri klasik Perl tarzında, diğeri ise Windows Script'in Scripting Dictionary nesnesiyle. Bu kodu dico.wsf dosyasına kaydedelim (wsf, Windows Script dosyalarının uzantısıdır). Programın bulunduğu klasöre gidelim ve programı çalıştıralım:

E:\data\serge\windowsScripting\perlscript\essais>cscript dico.wsf
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. Tous droits réservés.

clé=philippe, valeur=marianne
clé=maurice, valeur=juliette
juliette
marianne

Perlscript, içinde çalıştığı kapsayıcının nesnelerini kullanabilir. Burada bunlar Windows Script kapsayıcısının nesneleriydi. Web programlama bağlamında, VBscript, Javascript ve Perlscript komut dosyaları, ya tarayıcı içinde IE ya da bir sunucu içinde PWS veya IIS olarak çalıştırılabilir. Komut dosyası biraz karmaşıksa, daha önce görüldüğü gibi, onu web ortamı dışında, Windows Script kapsayıcısı içinde test etmek akıllıca olabilir. Bu şekilde, yalnızca tarayıcıya veya sunucuya özgü nesneleri kullanmayan komut dosyası işlevlerini test etmek mümkün olacaktır. Bu kısıtlamaya rağmen, bu seçenek yine de ilgi çekicidir; çünkü web sunucuları veya tarayıcılarda çalışan komut dosyalarını hata ayıklamak genellikle oldukça zahmetlidir.

8.1.7. JAVA

Java, URL adresinde mevcuttur: http://www.sun.com ve <java> olarak adlandıracağımız, aşağıdaki öğeleri içeren bir dizin yapısına kurulur:

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

bin dizininde javac.exe (Java derleyicisi) ve java.exe (Java sanal makinesi) bulunur. Aşağıdaki testleri yapabilirsiniz:

  1. Aşağıdaki komut dosyasını yazın:
//saati gösteren Java programı

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

public class heure{
  public static void main(String arg[]){
     // tarih ve saati alıyoruz
     Date maintenant=new Date();
      // görüntüleme
     System.out.println("Il est "+maintenant.getHours()+
        ":"+maintenant.getMinutes()+":"+maintenant.getSeconds());
  }//ana program
}//sınıf
  1. Bu programı heure.java adıyla kaydedin. DOS penceresini açın. heure.java dosyasının bulunduğu dizine gidin ve dosyayı derleyin:
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.

Yukarıdaki komutta c:\jdk1.3\bin\javac kısmı, javac.exe derleyicisinin tam yoluyla değiştirilmelidir. heure.java ile aynı dizinde, heure.class adlı bir dosya bulunmalıdır; bu dosya, java.exe sanal makinesi tarafından çalıştırılacak programdır.

  1. Programı çalıştırın:
D:\data\java\essais>c:\jdk1.3\bin\java heure
Il est 10:44:2

8.1.8. Apache Sunucusu

EasyPhp uygulamasıyla Apache sunucusunu edinebileceğimizi görmüştük. Doğrudan edinmek için Apache'nin web sitesine gideceğiz: http://www.apache.org. Kurulum, sunucu için gerekli tüm dosyaların bulunduğu bir dizin yapısı oluşturur. Bu dizine <apache> adını verelim. Dizin, aşağıdakine benzer bir yapıya sahiptir:

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
conf
Apache yapılandırma dosyalarının bulunduğu klasör
logs
Apache günlük dosyaları klasörü
bin
Apache'nin yürütülebilir dosyaları

8.1.8.1. Configuration

<Apache>\conf klasöründe şu dosyalar bulunur: httpd.conf, srm.conf, access.conf. Apache'nin son sürümlerinde bu üç dosya, httpd.conf dosyasında birleştirilmiştir. Bu yapılandırma dosyasının önemli noktalarını daha önce ele almıştık. Aşağıdaki örneklerde testler için EasyPhp sürümündeki Apache ve dolayısıyla bu sürümün yapılandırma dosyası kullanılmıştır. Bu dosyada, web sayfaları dizin yapısının kök dizinini belirten DocumentRoot, e:\program files\easyphp\www olarak belirtilmiştir.

8.1.8.2. PHP - Apache bağlantısı

Test etmek için, içinde yalnızca aşağıdaki satırın bulunduğu intro.php dosyasını oluşturun:

<? phpinfo() ?>

ve bu dosyayı Apache sunucusunun kök dizinine yerleştirin (yukarıdaki DocumentRoot). http://localhost/intro.php adresinden URL dosyasını çağırın. php bilgilerinin bir listesi görünmelidir:

Image

Aşağıdaki PHP komut dosyası saati gösterir. Bununla daha önce karşılaşmıştık:

<?php
   // zaman: 01/01/1970'ten bu yana geçen milisaniye sayısı
   // "tarih-saat görüntüleme biçimi
   // d: 2 basamaklı gün
   // m: 2 basamaklı ay
   // y: 2 basamaklı yıl
   // H: saat 0,23
   // i: dakika
   // s: saniye
  print "Nous sommes le " . date("d/m/y H:i:s",time());
?>

Bu metin dosyasını Apache sunucusunun kök dizinine (DocumentRoot) yerleştirelim ve adını date.php olarak değiştirelim. Bir tarayıcıyla URL adresini http://localhost/date.php şeklinde çağıralım. Aşağıdaki sayfa görüntülenir:

Image

8.1.8.3. PERL-APACHE bağlantısı

Bu, <apache>\conf\httpd.conf dosyasındaki ScriptAlias /cgi-bin/ "E:/Program Files/EasyPHP/cgi-bin/" biçimindeki bir satır sayesinde oluşturulur. Sözdizimi şöyledir: ScriptAlias /cgi-bin/ "<cgi-bin>" şeklindedir; burada <cgi-bin>, CGI komut dosyalarının yerleştirilebileceği klasördür. CGI (Common Gateway Interface), sunucu WEB ile uygulamalar arasındaki iletişim standardıdır. Bir istemci, web sunucusundan dinamik bir sayfa, yani bir program tarafından oluşturulan bir sayfa ister. Bu nedenle WEB sunucusu, sayfayı oluşturması için bir programa talepte bulunmalıdır. CGI, sunucu ile program arasındaki iletişimi, özellikle de bu iki varlık arasında bilgilerin aktarım şeklini tanımlar.

Gerekirse, ScriptAlias /cgi-bin/ "<cgi-bin>" satırını değiştirin ve Apache sunucusunu yeniden başlatın. Ardından şu testi yapın:

  1. Komut dosyasını yazın:
#!c:\perl\bin\perl.exe

# saati gösteren PERL komut dosyası

# modüller
use strict;

# program
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
;
  1. Bu betiği <cgi-bin>\heure.pl konumuna yerleştirin; burada <cgi-bin>, CGI betiklerini barındırabilecek klasördür (bkz. httpd.conf). İlk satırdaki #!c:\perl\bin\perl.exe ifadesi, perl.exe yürütülebilir dosyasının yolunu belirtir. Gerekirse bunu değiştirin.
  2. Henüz yapılmadıysa Apache’yi başlatın
  3. Bir tarayıcıdan URL adresine http://localhost/cgi-bin/heure.pl erişin. Aşağıdaki sayfa görüntülenir:

Image

8.1.9. PWS sunucusu

8.1.9.1. Installation

PWS sunucusu (Personal Web Server), Microsoft'un IIS sunucusunun (Internet Information Server) kişisel bir sürümüdür. Microsoft'un sunucusu, NT ve 2000 işletim sistemli makinelerde mevcuttur. Win9x sistemlerinde, PWS normalde Internet Explorer kurulum paketi ile birlikte gelir. Ancak varsayılan olarak yüklenmez. IE'in özel kurulumunu seçip PWS'in yüklenmesini talep etmeniz gerekir. Ayrıca, bu bileşen Windows 95 için NT 4.0 Option Pack'te de mevcuttur.

8.1.9.2. İlk testler

PWS sunucusundaki web sayfalarının kök dizini sürücü:\inetpub\wwwroot şeklindedir; burada sürücü, PWS'i kurduğunuz diski ifade eder. Bundan sonra bu sürücünün D olduğunu varsayıyoruz. Dolayısıyla http://machine/rep1/page1.html URL'si, d:\inetpub\wwwroot\rep1\page1.html dosyasına karşılık gelecektir. PWS sunucusu, .asp (Active Server Pages) uzantılı tüm dosyaları, bir HTML sayfası oluşturmak için çalıştırması gereken bir komut dosyası olarak yorumlar.

PWS varsayılan olarak 80 numaralı bağlantı noktasında çalışır. Apache web sunucusu da öyle... Dolayısıyla, her iki sunucuya da sahipseniz, PWS ile çalışmak için Apache'yi durdurmanız gerekir. Diğer bir çözüm ise Apache'yi başka bir bağlantı noktasında çalışacak şekilde yapılandırmaktır. Bunun için Apache yapılandırma dosyasında Port 80 satırını Port 81 ile değiştirirseniz, Apache artık 81 numaralı bağlantı noktasında çalışacak ve PWS ile aynı anda kullanılabilecektir. PWS başlatılmışken, URL http://localhost adresine erişildiğinde, aşağıdakine benzer bir sayfa görüntülenir:

Image

8.1.9.3. PHP - PWS bağlantısı

  1. Aşağıda, kayıt defterini değiştirmek için hazırlanmış bir .reg dosyası bulunmaktadır. Kayıt defterini değiştirmek için bu dosyaya çift tıklayın. Burada gerekli olan dll, php yürütülebilir dosyasıyla birlikte d:\php4 içinde yer almaktadır. Gerekirse değiştirin. DLL dosyasının yolunda \ karakterleri iki kez yazılmalıdır.
REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map]
".php"="d:\\php4\\php4isapi.dll"
  1. Kayıt defterindeki değişikliğin geçerli olması için sistemi yeniden başlatın.
  1. d:\inetpub\wwwroot'te (PWS sunucusunun kök dizini) bir php klasörü oluşturun. Bunu yaptıktan sonra, PWS'i etkinleştirin ve "Gelişmiş" sekmesine gidin. Sanal bir klasör oluşturmak için “Ekle” düğmesini seçin:
Répertoire/Parcourir : d:\inetpub\wwwroot\php
Alias : php
Cocher la case exécuter.
  1. Tüm değişiklikleri kaydedin ve PWS'i yeniden başlatın. d:\inetpub\wwwroot\php dosyasına, yalnızca aşağıdaki satırı içeren intro.php dosyasını ekleyin:
<? phpinfo() ?>
  1. PWS sunucusundan URL http://localhost/php/intro.php dosyasını isteyin. Apache ile daha önce görüntülenen PHP bilgileri listesi görünmelidir.

8.1.10. Tomcat: Java servletleri ve JSP sayfaları (Java Sunucu Sayfaları)

Tomcat, servletler (web sunucusu tarafından çalıştırılan Java programları) aracılığıyla HTML sayfaları veya Java kodu ile JSP kodunu birleştiren HTML sayfaları (Java Sunucu Sayfaları) oluşturmaya olanak tanıyan bir web sunucusudur. Bu, Microsoft’un IIS/PWS sunucusundaki ASP (Active Server Pages) sayfalarına eşdeğerdir; burada VBScript veya JavaScript kodu ile HTML kodu birleştirilir.

8.1.10.1. Installation

Tomcat, URL adresinde mevcuttur: http://jakarta.apache.org. Bir .exe kurulum dosyası indirilir. Bu programı çalıştırdığınızda, öncelikle hangi JDK'i kullanacağını belirtir. Nitekim Tomcat, kurulabilmesi ve ardından Java servlet'lerini derleyip çalıştırabilmesi için bir JDK'e ihtiyaç duyar. Bu nedenle, Tomcat’ı kurmadan önce bir Java sürümü yüklemiş olmanız gerekir. En güncel sürümün kullanılması tavsiye edilir. Kurulum, <tomcat> dizin yapısını oluşturacaktır:

Image

Kurulum, bu arşivi bir dizine açmaktan ibarettir. Yolunda boşluk içermeyen adlar bulunan bir dizin seçin (örneğin "Program Files" gibi olmamalıdır); bunun nedeni, Tomcat kurulum sürecinde bir hata bulunmasıdır. Örneğin C:\tomcat veya D:\tomcat gibi bir dizin seçin. Bu dizine <tomcat> diyelim. İçinde jakarta-tomcat adlı bir klasör bulunur ve bunun içinde de şu dizin yapısı yer alır:

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. Tomcat Web Sunucusunu Başlatma/Durdurma

Tomcat, Apache veya PWS gibi bir web sunucusudur. Sunucuyu başlatmak için programlar menüsünde bulunan bağlantıları kullanabilirsiniz:

Start Tomcat
Tomcat'i başlatmak için
Stop Tomcat
durdurmak için

Tomcat başlatıldığında, aşağıdaki içeriğe sahip bir DOS penceresi açılır:

Image

Bu DOS penceresini simge durumuna getirebilirsiniz. Tomcat aktif olduğu sürece pencere açık kalacaktır. Ardından ilk testlere geçebilirsiniz. Tomcat web sunucusu 8080 numaralı bağlantı noktasında çalışır. Tomcat başlatıldıktan sonra, bir web tarayıcısı açın ve http://localhost:8080 adresine erişin. Aşağıdaki sayfayı görmelisiniz:

Image

"Servlet Examples" bağlantısını takip edin:

Image

RequestParameters sayfasındaki Execute bağlantısına, ardından da Source bağlantısına tıklayın. Böylece Java servlet'in ne olduğu konusunda ilk fikir edinebilirsiniz. JSP sayfalarındaki bağlantılarla da aynı işlemi yapabilirsiniz.

Tomcat’i durdurmak için program menüsündeki “Stop Tomcat” bağlantısını kullanacağız.

8.1.11. Jbuilder

Jbuilder, bir Java uygulama geliştirme ortamıdır. Grafik arayüz içermeyen Java servlet'leri oluşturmak için böyle bir ortama sahip olmak zorunlu değildir. Bir metin düzenleyici ve bir JDK yeterlidir. Ancak JBuilder, önceki tekniğe kıyasla bazı avantajlar sunar:

  • hata ayıklama kolaylığı: derleyici, programdaki hatalı satırları bildirir ve bu satırlara kolayca ulaşılabilir
  • kod önerisi: Bir Java nesnesi kullanıldığında, JBuilder bu nesnenin özellik ve yöntemlerinin listesini satır içinde gösterir. Çoğu Java nesnesinin hatırlanması zor çok sayıda özelliğe ve yönteme sahip olduğu düşünüldüğünde, bu çok kullanışlıdır.

JBuilder'e http://www.borland.com/jbuilder adresinden ulaşılabilir. Yazılımı edinmek için bir form doldurulması gerekir. Etkinleştirme anahtarı e-posta ile gönderilir. Örneğin, JBuilder 7'yi kurmak için şu adımlar izlendi:

  • üç adet zip dosyası indirildi: uygulama, belgeler ve örnekler için. Bu zip dosyalarının her biri, JBuilder sitesinde ayrı bir bağlantı altında yer alıyor.
  • Önce uygulama, ardından belgeler ve son olarak örnekler yüklendi
  • Uygulamayı ilk kez başlattığınızda bir etkinleştirme anahtarı istenir: bu, size e-posta ile gönderilen anahtardır. Sürüm 7'de bu anahtar, aslında bir metin dosyasının tamamıdır ve örneğin JB7 kurulum klasörüne yerleştirilebilir. Anahtar istendiğinde, söz konusu dosyayı belirtmeniz yeterlidir. Bu işlem yapıldıktan sonra anahtar bir daha istenmeyecektir.

JBuilder'i Java servlet'leri oluşturmak için kullanmak istiyorsanız, yapılması gereken birkaç yararlı ayar vardır. Aslında, "kişisel Jbuilder" olarak adlandırılan sürüm, Java ile web geliştirme yapmak için gerekli tüm sınıfları içermeyen, hafifletilmiş bir sürümdür. JBuilder'in Tomcat tarafından sağlanan sınıf kütüphanelerini kullanmasını sağlayabilirsiniz. Bunun için şu adımları izleyin:

  • JBuilder'i çalıştırın

Image

  • Tools/Configure JDKs seçeneğini etkinleştirin

Image

Yukarıdaki JDK Ayarları bölümünde, Name alanında normalde JDK 1.3.1 yazmaktadır. Daha yeni bir JDK sürümünüz varsa, Change düğmesini kullanarak bu sürümün kurulum dizinini belirtin. Yukarıda, JDK 1.4 sürümünün kurulu olduğu E:\Program Files\jdk14 dizini belirtilmiştir. Artık JBuilder, derleme ve çalıştırma işlemleri için bu JDK sürümünü kullanacaktır. (Class, Source, Documentation) bölümünde, JBuilder tarafından taranacak tüm sınıf kütüphanelerinin listesi bulunur; burada JDK 1.4 sürümünün sınıfları yer almaktadır. Bu sürümün sınıfları, Java ile web geliştirme yapmak için yeterli değildir. Başka sınıf kütüphaneleri eklemek için Add düğmesini kullanır ve kullanmak istediğiniz ek .jar dosyalarını seçersiniz. .jar dosyaları, sınıf kütüphaneleridir. Tomcat 4.x, web geliştirme için gerekli tüm sınıf kütüphanelerini beraberinde getirir. Bunlar, <tomcat>\common\lib dizininde bulunur; burada <tomcat>, Tomcat'in kurulum dizinidir:

Image

Add düğmesini kullanarak bu kütüphaneleri tek tek JBuilder tarafından taranan kütüphane listesine ekleyeceğiz:

Image

Artık, J2EE standardına uygun Java programlarını, özellikle de Java servlet'lerini derleyebiliriz. JBuilder yalnızca derleme için kullanılır; yürütme işlemi ise derslerde açıklanan yöntemlere göre daha sonra Tomcat tarafından gerçekleştirilir.

8.2. Programların kaynak kodu

8.2.1. Genel TCP istemcisi

İnternetin ilk dönemlerinde oluşturulan birçok hizmet, daha önce incelediğimiz yankı sunucusu modeline göre çalışır: istemci-sunucu iletişimi, metin satırlarının alışverişi yoluyla gerçekleşir. Aşağıdaki şekilde başlatılacak genel bir TCP istemcisi yazacağız: java cltTCPgenerique sunucu bağlantı noktası

Bu TCP istemcisi, serveur sunucusunun port bağlantı noktasına bağlanacaktır. Bağlantı kurulduktan sonra, iki iş parçacığı oluşturacaktır:

  1. klavyeden girilen komutları okumak ve sunucuya göndermekle görevli bir iş parçacığı
  2. sunucudan gelen yanıtları okumak ve bunları ekrana görüntülemekle görevli bir iş parçacığı

Neden iki iş parçacığı? Her TCP-IP hizmeti kendine özgü bir protokole sahiptir ve bazen aşağıdaki durumlarla karşılaşılabilir:

  • istemci, yanıt alabilmek için birkaç satır metin göndermek zorundadır
  • bir sunucunun yanıtı birkaç satır metin içerebilir

Bu nedenle, sunucuya tek bir satır gönderme - sunucudan gelen tek bir satırı alma döngüsü her zaman uygun olmayabilir. Bu nedenle, birbirinden bağımsız iki döngü oluşturacağız:

  • klavyeden girilen ve sunucuya gönderilecek komutları okuma döngüsü. Kullanıcı, fin anahtar kelimesiyle komutların bittiğini bildirecektir.
  • sunucudan gelen yanıtları alıp görüntüleyen bir döngü. Bu, sunucu tarafından ağ akışının kapatılmasıyla veya kullanıcı tarafından klavyeden fin komutunun girilmesiyle kesilecek sonsuz bir döngü olacaktır.

Bu iki döngüyü birbirinden ayırmak için iki bağımsız iş parçacığına ihtiyacımız var. Genel tcp istemcimizin SMTP (SendMail Aktarım Protokolü) hizmetine bağlandığı bir yürütme örneğini inceleyelim. Bu hizmet, e-postaların alıcılara iletilmesinden sorumludur. 25 numaralı bağlantı noktasında çalışır ve metin satırları alışverişi türünde bir iletişim protokolüne sahiptir.

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]

Bu istemci-sunucu iletişimlerini inceleyelim:

  • SMTP hizmeti, bir istemci ona bağlandığında bir hoş geldiniz mesajı gönderir:
<-- 220 istia.univ-angers.fr ESMTP Sendmail 8.11.6/8.9.3; Mon, 13 May 2002 08:37:26 +0200
  • Bazı hizmetlerde, hizmetle kullanılabilecek komutlar hakkında bilgi veren help komutu bulunur. Burada durum böyle değildir. Örnekte kullanılan SMTP komutları şunlardır:
    • mail from: expéditeur, mesajın göndereninin e-posta adresini belirtmek için
    • rcpt to: destinataire, mesajın alıcısının e-posta adresini belirtmek için kullanılır. Birden fazla alıcı varsa, her alıcı için rcpt to: komutu gerektiği kadar tekrar gönderilir.
    • data, SMTP sunucusuna mesajın gönderileceğini bildirir. Sunucunun yanıtında belirtildiği gibi, bu mesaj, sadece nokta karakterini içeren bir satırla biten bir dizi satırdan oluşur. Bir mesajın, mesaj gövdesinden boş bir satırla ayrılmış başlıkları olabilir. Örneğimizde, Subject: anahtar kelimesini kullanarak bir konu başlığı ekledik:
  • Mesaj gönderildikten sonra, quit komutuyla sunucuya işin bittiğini bildirebiliriz. Sunucu daha sonra ağ bağlantısını kapatır. Okuma iş parçacığı bu olayı algılayabilir ve durabilir.
  • Kullanıcı, klavyeden "fin" yazarak klavyeden girilen komutları okuma iş parçacığını da durdurabilir.

Alınan postayı kontrol edersek, şunu görürüz (Outlook):

Image

SMTP hizmetinin, bir gönderenin geçerli olup olmadığını algılayamadığı dikkatinizi çekecektir. Bu nedenle, bir iletinin from alanına asla güvenilemez. Burada machin@univ-angers.fr adlı gönderen mevcut değildi.

Bu genel tcp istemcisi, internet hizmetlerinin iletişim protokolünü keşfetmemizi ve buradan yola çıkarak bu hizmetlerin istemcileri için özel sınıflar oluşturmamızı sağlayabilir. Bir sunucuda depolanan e-postaları bulmamızı sağlayan POP hizmetinin (Post Office Protocol) iletişim protokolünü inceleyelim. Bu hizmet 110 numaralı bağlantı noktasında çalışır.

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]

Başlıca komutlar şunlardır:

  • user login, burada e-postalarımızın bulunduğu makinedeki kullanıcı adımızı gireriz
  • pass password, burada önceki kullanıcı adıyla ilişkili şifre girilir
  • list, mesajların numara ve bayt cinsinden boyut bilgilerini içeren listesini almak için
  • retr i, i numaralı mesajı okumak için
  • quit, diyaloğu sonlandırmak için.

Şimdi, genellikle 80 numaralı bağlantı noktasında çalışan bir web sunucusuyla istemci arasındaki iletişim protokolünü inceleyelim:

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]

Bir web istemcisi, komutlarını aşağıdaki şemaya göre sunucuya gönderir:

commande1
commande2
...
commanden
[ligne vide]

Web sunucusu ancak boş satırı aldıktan sonra yanıt verir. Örnekte sadece bir komut kullandık:

GET /index.html HTTP/1.0

Bu komut, sunucudan URL /index.html dosyasını ister ve HTTP protokolünün 1.0 sürümüyle çalıştığını belirtir. Bu protokolün en güncel sürümü 1.1'dir. Örnekte, sunucunun index.html dosyasının içeriğini geri göndererek yanıt verdiği ve ardından yanıt okuma iş parçacığının sona erdiği görüldüğünden bağlantıyı kapattığı görülmektedir. index.html dosyasının içeriğini göndermeden önce, web sunucusu boş bir satırla biten bir dizi başlık göndermiştir:

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

<html> satırı, /index.html dosyasının ilk satırıdır. Yukarıdakiler, HTTP (HyperText Aktarım Protokolü) başlıkları olarak adlandırılır. Bu başlıkları burada ayrıntılı olarak ele almayacağız, ancak genel amaçlı istemcimizin bunlara erişim sağladığını hatırlayalım; bu, başlıkları anlamak açısından yararlı olabilir. Örneğin ilk satır:

<-- HTTP/1.1 200 OK

, erişilen web sunucusunun HTTP/1.1 protokolünü anladığını ve istenen dosyayı (200 OK) başarıyla bulduğunu gösterir; burada 200, bir HTTP yanıt kodudur. Şu satırlar:

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

satırları, istemciye HTML (HyperText İşaretleme Dili) metnini temsil eden 11251 bayt alacağını ve gönderimin sonunda bağlantının kapatılacağını bildirir.

Dolayısıyla burada çok kullanışlı bir TCP istemcisi var. Kuşkusuz resmi telnet programından daha az işlev sunuyor, ancak bunu kendimiz yazmak ilginçti. Genel amaçlı TCP istemcisi programı şöyledir:

// ithal edilen paketler
import java.io.*;
import java.net.*;

public class clientTCPgenerique{

    // bir hizmetin özelliklerini şu biçimde parametre olarak alır
     // sunucu bağlantı noktası
     // hizmete bağlanır
     // klavyeden girilen komutları okumak için bir iş parçacığı oluşturur
     // bu komutlar sunucuya gönderilir
     // sunucudan gelen yanıtları okumak için bir iş parçacığı oluşturur
     // bu yanıtlar ekranda görüntülenecek
     // tüm işlem, klavyeden girilen "fin" komutuyla sona erer

   // örnek değişkeni
  private static Socket client;

    public static void main(String[] args){

         // sözdizimi
        final String syntaxe="pg serveur port";

         // argüman sayısı
        if(args.length != 2)
            erreur(syntaxe,1);

         // sunucu adı yazılır
        String serveur=args[0];

         // bağlantı noktası >0 olan bir tamsayı olmalıdır
        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;
         // sorunlar yaşanabilir
        try{
             // hizmete bağlanılır
            client=new Socket(serveur,port);
        }catch(Exception ex){
             // hata
            erreur("Impossible de se connecter au service ("+ serveur
                +","+port+"), erreur : "+ex.getMessage(),3);
             // son
            return;
        }//yakalama

         // okuma/yazma iş parçacıkları oluşturuluyor
    new ClientSend(client).start();
    new ClientReceive(client).start();

         // ana iş parçacığı sonu
        return;
    }// ana iş parçacığı

     // hataların görüntülenmesi
    public static void erreur(String msg, int exitCode){
         // hata görüntüleme
        System.err.println(msg);
         // hata ile durdurma
        System.exit(exitCode);
    }//hata
}//sınıf  

class ClientSend extends Thread {
    // klavyeden girilen komutları okumakla görevli sınıf
     // ve bunları parametre olarak geçirilen bir TCP istemcisi aracılığıyla bir sunucuya göndermekle görevli sınıf

    private Socket client;    // TCP istemcisi

     // yapıcı
    public ClientSend(Socket client){
         // burada TCP istemcisi belirtilir
        this.client=client;
    }//oluşturucu

     // iş parçacığının Run yöntemi
    public void run(){

        // yerel veriler
        PrintWriter OUT=null;            // ağ yazma akışı
    BufferedReader IN=null;        // klavye akışı
        String commande=null;            // klavyeden okunan komut

         // hata yönetimi
        try{
             // ağ yazma akışının oluşturulması
            OUT=new PrintWriter(client.getOutputStream(),true);
      // klavye giriş akışının oluşturulması
      IN=new BufferedReader(new InputStreamReader(System.in));
            // komut girişi-gönderme döngüsü
            System.out.println("Commandes : ");
            while(true){
                 // klavyeden girilen komutun okunması
                commande=IN.readLine().trim();
                 // bitti mi?
                if (commande.toLowerCase().equals("fin")) break;
                // komutu sunucuya gönderme
                OUT.println(commande);
                 // sonraki komut
            }//while
        }catch(Exception ex){
             // hata
            System.err.println("Envoi : L'erreur suivante s'est produite : " + ex.getMessage());
        }//catch
         // son - akışlar kapatılıyor
        try{
            OUT.close();client.close();
        }catch(Exception ex){}
         // iş parçacığının sonu bildiriliyor
        System.out.println("[Envoi : fin du thread d'envoi des commandes au serveur]");
    }//çalıştır
}//sınıf

class ClientReceive extends Thread{
    // bir 
     // parametre olarak geçirilen bir TCP istemcisine yönelik metin satırlarını okumakla görevli sınıf

    private Socket client;    // TCP istemcisi

     // yapıcı
    public ClientReceive(Socket client){
         // TCP istemcisi kaydedilir
        this.client=client;
    }//oluşturucu

     // iş parçacığının Run yöntemi
    public void run(){

        // yerel veriler
        BufferedReader IN=null;        // ağ okuma akışı
        String réponse=null;        // sunucu yanıtı

         // hata yönetimi
        try{
             // ağ okuma akışının oluşturulması
            IN=new BufferedReader(new InputStreamReader(client.getInputStream()));
            // IN akışındaki metin satırlarını okuma döngüsü
            while(true){
                 // ağ akışını okuma
                réponse=IN.readLine();
                 // akış kapalı mı?
                if(réponse==null) break;
                // görüntüleme
                System.out.println("<-- "+réponse);
            }//while
        }catch(Exception ex){
            // hata
            System.err.println("Réception : L'erreur suivante s'est produite : " + ex.getMessage());
        }//yakalama
         // son - akışlar kapatılıyor
        try{
            IN.close();client.close();
        }catch(Exception ex){}
         // iş parçacığının sonu bildiriliyor
        System.out.println("[Réception : fin du thread de lecture des réponses du serveur]");
    }//çalıştır
}//sınıf

8.2.2. Genel TCP sunucusu

Şimdi,

  • bu sunucu, istemcilerinden gelen komutları ekrana yansıtır
  • ve yanıt olarak kullanıcının klavyeden girdiği metin satırlarını onlara gönderen bir sunucuya odaklanacağız. Dolayısıyla sunucu rolünü üstlenen kişi kullanıcıdır.

Program şu komutla çalıştırılır: java serveurTCPgenerique portEcoute; burada portEcoute, istemcilerin bağlanması gereken bağlantı noktasıdır. İstemciye hizmet, iki iş parçacığı tarafından sağlanacaktır:

  • bir iş parçacığı, yalnızca istemci tarafından gönderilen metin satırlarını okumaya adanmıştır
  • diğeri ise yalnızca kullanıcının klavyeden girdiği yanıtları okumaya adanmış bir iş parçacığıdır. Bu iş parçacığı, fin komutuyla istemciyle olan bağlantıyı sonlandırdığını bildirir.

Sunucu, her müşteri için iki iş parçacığı oluşturur. n müşteri varsa, aynı anda 2n aktif iş parçacığı olacaktır. Sunucu, kullanıcı tarafından klavyeden Ctrl-C tuşlarına basılmadıkça asla durmaz. Birkaç örneğe bakalım.

Sunucu 100 numaralı bağlantı noktasında çalıştırılır ve sunucuyla iletişim kurmak için genel amaçlı istemci kullanılır. İstemci penceresi şöyledir:

E:\data\serge\MSNET\c#\ağ\genel tcp istemcisi> 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]

<-- ile başlayan satırlar sunucudan istemciye gönderilenler, diğerleri ise istemciden sunucuya gönderilenlerdir. Sunucu penceresi şu şekildedir:


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]

<-- ile başlayan satırlar, istemciden sunucuya gönderilen satırlardır. N: ile başlayan satırlar, sunucudan N numaralı istemciye gönderilen satırlardır. Yukarıdaki sunucu hâlâ aktifken, istemci 1 işlemi tamamlanmıştır. Aynı sunucu için ikinci bir istemci başlatılır:


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]

Sunucu penceresi şu şekildedir:


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

Şimdi, genel sunucumuzu 88 numaralı bağlantı noktasında başlatarak bir web sunucusu simülasyonu yapalım:


Dos> java serveurTCPgenerique 88
Serveur générique lancé sur le port 88

Şimdi bir tarayıcı açalım ve URL http://localhost:88/exemple.html adresini girelim. Tarayıcı, localhost makinesinin 88 bağlantı noktasına bağlanacak ve ardından /exemple.html sayfasını isteyecektir:

Image

Şimdi sunucumuzun penceresine bakalım:

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

Böylece tarayıcı tarafından gönderilen HTTP başlıklarını görüyoruz. Bu, HTTP protokolünü yavaş yavaş keşfetmemizi sağlıyor. Önceki bir örnekte, yalnızca GET komutunu gönderen bir web istemcisi oluşturmuştuk. Bu yeterli olmuştu. Burada tarayıcının sunucuya başka bilgiler de gönderdiğini görüyoruz. Bu bilgilerin amacı, sunucuya karşısındaki istemcinin türünü belirtmektir. Ayrıca HTTP başlıklarının boş bir satırla bittiğini de görüyoruz.

Müşterimize bir yanıt hazırlayalım. Burada klavyeyi kullanan kullanıcı asıl sunucudur ve yanıtı elle hazırlayabilir. Önceki bir örnekte bir web sunucusu tarafından verilen yanıtı hatırlayalım:

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

Benzer bir cevap vermeye çalışalım:

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

2: ile başlayan satırlar, sunucudan 2 numaralı istemciye gönderilir. fin komutu, sunucuyla istemci arasındaki bağlantıyı sonlandırır. Yanıtımızda aşağıdaki HTTP başlıklarıyla sınırlı kaldık:

HTTP/1.1 200 OK
2 : Server: serveur tcp generique
2 : Connection: close
2 : Content-Type: text/html
2 :

Göndereceğimiz dosyanın boyutunu (Content-Length) belirtmiyoruz, ancak dosyayı gönderdikten sonra bağlantıyı kapatacağımızı (Connection: close) söylüyoruz. Bu, tarayıcı için yeterlidir. Bağlantının kapandığını görünce, tarayıcı sunucudan gelen yanıtın tamamlandığını anlayacak ve kendisine gönderilen HTML sayfasını görüntüleyecektir. Bu sayfa şöyledir:

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>

Kullanıcı daha sonra fin komutunu girerek istemciyle olan bağlantıyı kapatır. Tarayıcı, sunucudan gelen yanıtın tamamlandığını anlar ve yanıtı görüntüleyebilir:

Image

Yukarıdaki örnekte, tarayıcının ne aldığını görmek için View/Source komutunu girersek şu sonucu alırız:

Image

yani genel sunucudan gönderdiğimizin aynısı.

Genel TCP sunucusunun kodu şöyledir:

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

public class serveurTCPgenerique{

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

    // dinleme bağlantı noktasını alır ve istemcilerin isteklerini dinler
     // istemcilerin isteklerini okumak için bir  parçacığı oluşturur
     // bu istekler ekranda görüntülenecek
     // klavyeden girilen komutları okumak için bir  parçacığı oluşturur
     // bu komutlar müşteriye yanıt olarak gönderilir
     // tüm işlem, klavyeden girilen "fin" komutuyla sona erer

    final String syntaxe="Syntaxe : pg port";
   // örnek değişkeni
         // bir argüman var 
     if(args.length != 1)
        erreur(syntaxe,1);

         // bağlantı noktası >0 olan bir tamsayı olmalıdır
        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);

     // dinleme hizmeti oluşturulur
    ServerSocket ecoute=null;
    int nbClients=0;    // işlenen istemci sayısı
        try{
             // hizmet oluşturuluyor
            ecoute=new ServerSocket(port);
             // izleme
            System.out.println("Serveur générique lancé sur le port " + port);

             // müşterilere hizmet döngüsü
            Socket client=null;
            while (true){ // sonsuz döngü - Ctrl-C ile durdurulur
                 // bir istemciyi bekliyor
                client=ecoute.accept();

                 // hizmet, ayrı  parçacıklarıyla sağlanır
                nbClients++;

                 // okuma/yazma  parçacıkları oluşturuluyor
        new ServeurSend(client,nbClients).start();
        new ServeurReceive(client,nbClients).start();

                // istekleri dinlemeye geri dönülüyor
            }// while döngüsünün sonu
        }catch(Exception ex){
             // hata bildirilir
            erreur("L'erreur suivante s'est produite : " + ex.getMessage(),3);
        }//catch
    }// main sonu

     // hataların görüntülenmesi
    public static void erreur(String msg, int exitCode){
         // hatanın görüntülenmesi
        System.err.println(msg);
         // hata ile durdurma
        System.exit(exitCode);
    }//hata
}//sınıf

class ServeurSend extends Thread{
    // klavyeden girilen yanıtları okumakla görevli sınıf
     // ve bunları yapıcıya aktarılan bir TCP istemcisi aracılığıyla bir istemciye göndermekle görevli sınıf

    Socket client;    // TCP istemcisi
    int numClient;        // istemci numarası

     // yapıcı
    public ServeurSend(Socket client, int numClient){
         // burada TCP istemcisi not edilir
        this.client=client;
         // ve numarası
        this.numClient=numClient;
    }//üretici

     //  parçacığının Run yöntemi
    public void run(){

        // yerel veriler
        PrintWriter OUT=null;        //  yazma akışı
        String réponse=null;        // klavyeden okunan yanıt
    BufferedReader IN=null;    // klavye akışı

        // izleme
        System.out.println("Thread de lecture des réponses du serveur au client "+ numClient + " lancé");
         // hata yönetimi
        try{
             //  yazma akışının oluşturulması
            OUT=new PrintWriter(client.getOutputStream(),true);
      // klavye akışının oluşturulması
      IN=new BufferedReader(new InputStreamReader(System.in));
            // komut girişi-gönderme döngüsü
            while(true){
                 // müşteri kimlik doğrulaması
                System.out.print("--> " + numClient + " : ");
                 // klavyeden girilen yanıtın okunması
                réponse=IN.readLine().trim();
                // bitti mi?
                if (réponse.toLowerCase().equals("fin")) break;
                // yanıtın sunucuya gönderilmesi
                OUT.println(réponse);
                 // sonraki yanıt
            }//while
        }catch(Exception ex){
             // hata
            System.err.println("L'erreur suivante s'est produite : " + ex.getMessage());
        }//yakalama
         // son - akışlar kapatılıyor
        try{
            OUT.close();client.close();
        }catch(Exception ex){}
         //  parçacığının sonu bildiriliyor
        System.out.println("[fin du Thread de lecture des réponses du serveur au client "+ numClient+ "]");
    }//çalıştır
}//sınıf

class ServeurReceive extends Thread{
    // sunucuya gönderilen metin satırlarını okumakla görevli sınıf 
     // yapıcıya aktarılan bir TCP istemcisi aracılığıyla

    Socket client;    // TCP istemcisi
    int numClient;        // istemci numarası

     // yapıcı
    public ServeurReceive(Socket client, int numClient){
         // TCP istemcisi not edilir
        this.client=client;
         // ve numarası
        this.numClient=numClient;
    }//üretici

     //  parçacığının Run yöntemi
    public void run(){

        // yerel veriler
        BufferedReader IN=null;        //  okuma akışı
        String réponse=null;        // sunucu yanıtı

         // takip
        System.out.println("Thread de lecture des demandes du client "+ numClient + " lancé");
         // hata yönetimi
        try{
             //  okuma akışının oluşturulması
            IN=new BufferedReader(new InputStreamReader(client.getInputStream()));
            // IN akışındaki metin satırlarını okuma döngüsü
            while(true){
                 //  akışını okuma
                réponse=IN.readLine();
                 // akış kapalı ?
                if(réponse==null) break;
                // görüntüleme
                System.out.println("<-- "+réponse);
            }//while
        }catch(Exception ex){
            // hata
            System.err.println("L'erreur suivante s'est produite : " + ex.getMessage());
        }//yakalama
         // son - akışlar kapatılıyor
        try{
            IN.close();client.close();
        }catch(Exception ex){}
         //  parçacığının sonu bildiriliyor
        System.out.println("[fin du Thread de lecture des demandes du client "+ numClient+"]");
    }//çalıştır
}//sınıf

8.3. JAVASCRIPT

Bu bölümde, WEB sayfalarında JavaScript'in kullanımına ilişkin üç örnek sunuyoruz. Formların yönetimine odaklanıyoruz, ancak JavaScript çok daha fazlasını yapabilir.

8.3.1. Formdan bilgi alma

Aşağıdaki örnek, kullanıcının bir forma girdiği verilerin tarayıcı içinde nasıl alınacağını göstermektedir. Bu, genellikle verileri sunucuya göndermeden önce ön işleme tabi tutmaya olanak tanır.

8.3.1.1. Form

En yaygın bileşenleri içeren bir formumuz ve kullanıcının yaptığı girişleri görüntülemek için bir "Görüntüle" düğmesi var.

Image

8.3.1.2. Kod

<html>

  <head>
    <title>Un formulaire traité par Javascript</title>
    <script language="javascript">
      function afficher(){
         // form bilgilerini bir listede görüntüler

         // önce siliniyor
        effacerInfos();

         // # alanlarının değerlerini görüntüler
        with(document.frmExemple){
           // gizli alan
          ecrire("champ caché="+cache.value);
           // tekli metin alanı
          ecrire("champ textuel simple="+simple.value);
           // çoklu metin alanı
          ecrire("champ textuel multiple="+lignes.value);
          // radyo düğmeleri
          for(i=0;i<radio.length;i++){
            texte="radio["+i+"]="+radio[i].value;
            if(radio[i].checked) texte+=", coché";
            ecrire(texte);
          }//for
             // onay kutuları
          for(i=0;i<qcm.length;i++){
            texte="qcm["+i+"]="+qcm[i].value;
            if(qcm[i].checked) texte+=", coché";
            ecrire(texte);
          }//for
           //açılır liste
          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);
          }//için
           //çoktan seçmeli liste
          for(i=0;i<lstVoitures.length;i++){
            texte="lstVoitures["+i+"]="+lstVoitures.options[i].text;
            if(lstVoitures.options[i].selected) texte+=",sélectionné";
            ecrire(texte);
          }//for
           //şifre
          ecrire("mot de passe="+passwd.value);
        }//ile
      }//işlev

      function ecrire(texte){
         // bilgi listesine metin yazıyor
        frmInfos.lstInfos.options[frmInfos.lstInfos.length]=new Option(texte);
      }//yazma

      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">&nbsp;</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">&nbsp;</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>&nbsp;</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>&nbsp;</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. Javascript'te düzenli ifadeler

Tarayıcı tarafında, kullanıcı tarafından girilen verilerin sunucuya gönderilmeden önce geçerliliğini kontrol etmek için JavaScript kullanılabilir. İşte bu düzenli ifadeleri test eden bir program.

8.3.2.1. Test sayfası

Image

8.3.2.2. Sayfanın kodu

<html>

  <head>
    <title>Les expressions régulières en Javascript</title>
    <script language="javascript">
      function afficherInfos(){
        with(document.frmRegExp){
           // yapılması gereken bir şey mi var?
          if (! verifier()) return;
          // tamam - önceki sonuçları siliyoruz
          effacerInfos();
           // şablon kontrolü
          modele=new RegExp(txtModele.value);
          champs=modele.exec(txtChaine.value);
          if(champs==null)
             // model ile dize arasında eşleşme yok
            ecrireInfos("pas de correspondance");
          else{
             // eşleşme var - elde edilen sonuçlar görüntüleniyor
            ecrireInfos("Il y a correspondance");
            for(i=0;i<champs.length;i++)
              ecrireInfos("champs["+i+"]=["+champs[i]+"]");
          }//aksi takdirde
        }//with
      }//işlev

      function ecrireInfos(texte){
        // bilgi listesine metin yazıyor
        document.frmRegExp.lstInfos.options[document.frmRegExp.lstInfos.length]=new Option(texte);
      }//yaz

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

      function jouer(){
         // şablonu, seçilen örnekteki dizeyle karşılaştırır
        with(document.frmRegExp){
          txtModele.value=lstModeles.options[lstModeles.selectedIndex].text
          txtChaine.value=lstChaines.options[lstChaines.selectedIndex].text
          afficherInfos();
        }//ile
      }//çalıştır

      function ajouter(){
         //mevcut testi örneklere ekler
        with(document.frmRegExp){
          // yapılması gereken bir şey var mı?
          if (! verifier()) return;
           // ekleme
          lstModeles.options[lstModeles.length]=new Option(txtModele.value);
          lstChaines.options[lstChaines.length]=new Option(txtChaine.value);
           // girişleri sıfırla
          txtModele.value="";
          txtChaine.value="";
        }//ile
      }//ekle

      function verifier(){
         // giriş alanlarının boş olmadığını kontrol et
        with(document.frmRegExp){
          champs=/^\s*$/.exec(txtModele.value);
          if(champs!=null){
            alert("Vous n'avez pas indiqué de modèle");
            txtModele.focus();
            return false;
          }//eğer
          champs=/^\s*$/.exec(txtChaine.value);
          if(champs!=null){
            alert("Vous n'avez pas indiqué de chaîne de test");
            txtChaine.focus();
            return false;
          }//eğer
           // tamam
          return true;
        }//ile
      }//kontrol et
    </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. JavaScript'te liste yönetimi

8.3.3.1. Form

Image

8.3.3.2. Kod

<html>

  <head>
    <title>Les listes en Javascript</title>

    <script language="javascript">
       // ekle
      function ajouter(L1,L2,T){
         // T alanının değerini L1 ve L2 listelerine ekle
           // yapılması gereken bir şey var mı?
          champs=/^\s*$/.exec(T.value);
          if(champs!=null){
            // alan boş
            alert("Vous n'avez pas indiqué la valeur à ajouter");
            txtElement.focus();
            return;
          }//if
           // öğeyi ekliyoruz
          L1.options[L1.length]=new Option(T.value);
          L2.options[L2.length]=new Option(T.value);
          T.value="";
      }//ekle

       //boşalt
      function vider(L){
         // L listesini boşalt
        L.length=0;
      }//boşalt

      //aktarma
      function transfert(L1,L2,simple){
        //, L1 listesinden seçilen öğeleri L2'e aktar

         // yapılması gereken bir şey mi var?
         // L1'te seçilen öğenin dizini
        index1=L1.selectedIndex;
        if(index1==-1){
          alert("Vous n'avez pas sélectionné d'élément");
          return;
        }//if
         // listelerdeki öğelerin seçim modu nedir
        if(simple){ // tekli seçim
          element1=L1.options[index1].text;
           //L2'te ekleme
          L2.options[L2.length]=new Option(element1);
          //L1'te silme
          L1.options[index1]=null;
        }//tekli
        if(! simple){ //çoklu seçim
           //liste 1'i ters yönde tarama
          for(i=L1.length-1;i>=0;i--){
            //öğe seçildi mi?
            if(L1.options[i].selected){
               //L2'e ekleniyor
              L2.options[L2.length]=new Option(L1.options[i].text);
              //L1'ten siliniyor
              L1.options[i]=null;
            }//eğer
          }//for i
        }//if ! basit
      }//aktarım
   </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>