Skip to content

8. پیوست‌ها

8.1. ابزارهای توسعه وب

در اینجا توضیح می‌دهیم که ابزارهای مورد نیاز برای توسعه وب را از کجا پیدا کرده و چگونه نصب کنید. برخی از ابزارها به‌روزرسانی شده‌اند و دستورالعمل‌های ارائه‌شده در اینجا ممکن است دیگر برای آخرین نسخه‌ها صدق نکنند. بنابراین خوانندگان باید متناسب با آن خود را وفق دهند… در دوره برنامه‌نویسی وب، ما عمدتاً از ابزارهای زیر استفاده خواهیم کرد که همگی به‌صورت رایگان در دسترس هستند:

  • یک مرورگر وب جدید که قادر به نمایش XML باشد. مثال‌های این دوره با Internet Explorer 6 آزمایش شده‌اند.
  • یک JDK (مجموعه توسعه جاوا) جدید. مثال‌های این دوره با JDK 1.4 آزمایش شده‌اند. این JDK شامل پلاگین جاوا 1.4 برای مرورگرهای وب است که به آن‌ها امکان نمایش اپلکت‌های جاوا با استفاده از جاوا 1.4 را می‌دهد.
  • یک محیط توسعهٔ جاوا برای نوشتن سرولیت‌های جاوا. در این مورد، این JBuilder 7 است.
  • سرورهای وب: آپاچی، PWS (سرور وب شخصی)، تام‌کت.
    • Apache برای توسعهٔ برنامه‌های وب در PERL (Practical Extracting and Reporting Language) یا PHP (Personal Home Page) استفاده خواهد شد.
    • PWS برای توسعه برنامه‌های وب در ASP (صفحات سرور فعال) یا PHP استفاده خواهد شد
    • تام‌کت برای توسعه برنامه‌های وب با استفاده از سرولت‌های جاوا یا JSP (صفحات سرور جاوا) استفاده خواهد شد.
  • یک برنامه مدیریت پایگاه داده: MySQL
  • EasyPHP: ابزاری که سرور وب آپاچی، زبان PHP و SGBD MySQL را گرد هم می‌آورد

8.1.1. سرورهای وب، مرورگرها، زبان‌های اسکریپتی

  1. سرورهای وب اصلی
    • اپاچی (لینوکس، ویندوز)
    • سرور اطلاعات اینترنت IIS (NT)، سرور وب شخصی PWS (ویندوز 9x)
  1. مرورگرهای اصلی
    • اینترنت اکسپلورر (ویندوز)
    • نت‌اسکیپ (لینوکس، ویندوز)
  1. زبان‌های اسکریپت‌نویسی سمت سرور
    • VBScript (IIS, PWS)
    • JavaScript (IIS, PWS)
    • پِرل (آپاچی، IIS, PWS)
    • PHP (Apache, IIS, PWS)
    • جاوا (اپاچی، تامکت)
    • زبان‌ها .NET
  1. زبان‌های اسکریپت‌نویسی سمت مرورگر
    • VBScript (IE)
    • جاوااسکریپت (IE, نت‌اسکیپ)
    • PerlScript (IE)
    • جاوا (IE, Netscape)

8.1.2. ابزارها را از کجا پیدا کنیم

Netscape
http://www.netscape.com/ (لینک دانلود)
Internet Explorer
http://www.microsoft.com/windows/ie/default.asp
PHP
http://www.php.net
http://www.php.net/downloads.php (بیتابی‌های ویندوز)
PERL
http://www.activestate.com http://www.activestate.com/Products/
http://www.activestate.com/Products/ActivePerl/
Vbscript, Javascript
http://msdn.microsoft.com/scripting (لینک اسکریپت ویندوز را دنبال کنید)
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 برای ویندوز 95
شامل در Windows 98 CD
http://www.microsoft.com/ntserver/nts/downloads/recommended/NT4OptPk/win95.asp
IIS 
(windows NT/2000)
http://www.microsoft.com
Tomcat
http://jakarta.apache.org/tomcat/
JBuilder
http://www.borland.com/jbuilder/
http://www.borland.com/products/downloads/download_jbuilder.html
EasyPHP
http://www.easyphp.org/
http://www.easyphp.org/telechargements.php3

8.1.3. EasyPHP

این برنامه بسیار کاربردی است زیرا موارد زیر را در یک بسته واحد ترکیب می‌کند:

  • سرور وب آپاچی (1.3.x)
  • زبان PHP (4.x)
  • SGBD MySQL (3.23.x)
  • یک ابزار مدیریتی برای MySQL: PhpMyAdmin

برنامهٔ نصب به شرح زیر ساختار یافته است:

Image

نصب EasyPHP بدون هیچ مشکلی انجام می‌شود و ساختار دایرکتوری در سیستم فایل ایجاد می‌شود:

Image

easyphp.exe
فایل اجرایی برنامه
apache
ساختار دایرکتوری سرور آپاچی
mysql
ساختار دایرکتوری MySQL SGBD
phpmyadmin
ساختار دایرکتوری برنامه phpMyAdmin
php
ساختار دایرکتوری PHP
www
ریشه ساختار دایرکتوری صفحات وب ارائه‌شده توسط سرور آپاچی در EasyPHP
cgi-bin
ساختار دایرکتوری که اسکریپت‌های CGI می‌توانند در آن برای سرور آپاچی قرار گیرند

مزیت اصلی EasyPHP این است که برنامه از پیش پیکربندی شده است. این بدان معناست که Apache، PHP و MySQL قبلاً برای کار با یکدیگر تنظیم شده‌اند. وقتی EasyPhp را از طریق میانبر آن در منوی استارت اجرا می‌کنید، یک آیکون در گوشه پایین سمت راست صفحه ظاهر می‌شود.

این همان حرف «E» با یک نقطه قرمز است که در صورت عملیاتی بودن سرور وب Apache و پایگاه داده MySQL باید چشمک بزند. کلیک راست روی آن منوی زیر را نمایش می‌دهد:

Image

گزینه Administration به شما امکان می‌دهد تنظیمات را پیکربندی کرده و تست‌های عملکردی را انجام دهید:

Image

8.1.3.1. اداره PHP

دکمه «اطلاعات PHP» باید به شما امکان دهد تا بررسی کنید که ترکیب Apache-PHP به درستی کار می‌کند: یک صفحه اطلاعاتی (PHP) باید ظاهر شود:

Image

دکمه «Extensions» فهرستی از افزونه‌های نصب‌شده برای PHP را نمایش می‌دهد. این‌ها در واقع کتابخانه‌های تابع هستند.

Image

تصویر بالا، برای مثال، نشان می‌دهد که توابع مورد نیاز برای استفاده از پایگاه داده MySQL در واقع موجود هستند.

دکمه «تنظیمات» صفحهٔ login/motdepasse را برای مدیر پایگاه دادهٔ MySQL نمایش می‌دهد.

Image

استفاده از پایگاه داده MySQL خارج از محدوده این مرور مختصر است، اما در اینجا واضح است که باید یک رمز عبور برای مدیر پایگاه داده تعیین شود.

8.1.3.2. مدیریت آپاچی

هنوز در صفحهٔ مدیریت EasyPHP، لینک «Your aliases» به شما امکان می‌دهد تا نام‌های مستعار مرتبط با یک دایرکتوری را تعریف کنید. این کار به شما اجازه می‌دهد صفحات وب را در مکان‌های دیگری غیر از دایرکتوری www در ساختار دایرکتوری easyPhp قرار دهید.

Image

اگر در صفحه بالا، اطلاعات زیر را وارد کنید:

Image

و دکمه valider را کلیک کنیم، خطوط زیر به فایل <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> به دایرکتوری نصب EasyPHP اشاره دارد. httpd.conf فایل پیکربندی سرور آپاچی است. بنابراین می‌توانید با ویرایش مستقیم این فایل به نتیجه مشابهی دست یابید. تغییرات اعمال‌شده بر روی فایل httpd.conf معمولاً بلافاصله توسط آپاچی در نظر گرفته می‌شوند. اگر این اتفاق نیفتاد، باید سرویس را متوقف کرده و سپس مجدداً با استفاده از آیکون EasyPHP آن را راه‌اندازی کنید:

Image

برای تکمیل مثال خود، اکنون می‌توانیم صفحات وب را در ساختار دایرکتوری e:\data\serge\web قرار دهیم:

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

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

و این صفحه را با استفاده از نام مستعار «st» درخواست کنیم:

Image

در این مثال، سرور آپاچی برای اجرا روی پورت 81 پیکربندی شده است. پورت پیش‌فرض آن 80 است. این توسط خط زیر در فایل httpd.conf که قبلاً با آن مواجه شده‌ایم، کنترل می‌شود:

Port 81

8.1.3.3. فایل پیکربندی آپاچی htpd.conf

وقتی می‌خواهید پیکربندی آپاچی را بهینه‌سازی کنید، باید فایل پیکربندی آن httpd.conf را «به صورت دستی» ویرایش کنید؛ این فایل در این مکان در پوشه <easyphp>\apache\conf قرار دارد:

Image

در اینجا چند نکته کلیدی از این فایل پیکربندی آورده شده است:

ligne(s)
نقش
ServerRoot "D:/Program Files/Apache Group/Apache"
نشان‌دهنده پوشه‌ای است که ساختار دایرکتوری آپاچی را در خود دارد
Port 80
پورتی را مشخص می‌کند که وب‌سرور روی آن اجرا خواهد شد. معمولاً این عدد ۸۰ است. با تغییر این خط، می‌توانید وب‌سرور را روی پورت متفاوتی اجرا کنید.
ServerAdmin root@istia.univ-angers.fr
آدرس ایمیل مدیر سرور آپاچی
ServerName stahe.istia.uang
نام ماشینی که سرور آپاچی روی آن در حال اجرا است
ServerRoot "E:/Program Files/EasyPHP/apache"
پوشه نصب سرور آپاچی. وقتی نام‌های فایل نسبی در فایل پیکربندی ظاهر می‌شوند، نسبت به این پوشه هستند.
DocumentRoot "E:/Program Files/EasyPHP/www"
زیرپوشه ریشه ساختار درختی صفحات وب ارائه‌شده توسط سرور. در اینجا، URL http://machine/rep1/fic1.html به فایل E:\Program Files\EasyPHP\www\rep1\fic1.html
<Directory "E:/Program Files/EasyPHP/www">
ویژگی‌های پوشه قبلی را تنظیم می‌کند
ErrorLog logs/error.log
پوشهٔ لاگ، بنابراین در واقع <ServerRoot>\logs\error.log: E:\Program Files\EasyPHP\apache\logs\error.log. این فایلی است که باید بررسی کنید اگر متوجه شدید سرور آپاچی کار نمی‌کند.
    ScriptAlias /cgi-bin/ "E:/Program Files/EasyPHP/cgi-bin/"
E:\Program Files\EasyPHP\cgi-bin ریشه ساختار دایرکتوری است که می‌توانید اسکریپت‌های CGI را در آن قرار دهید. بنابراین، URL اسکریپت CGI E:\http://machine/cgi-bin/rep1/script1.pl خواهد بود: URLhttp://machine/cgi-bin/rep1/script1.pl.Program Files\EasyPHP\cgi-bin\rep1\script1.pl.
<Directory "E:/Program Files/EasyPHP/cgi-bin/">
ویژگی‌های پوشهٔ بالا را تنظیم می‌کند
LoadModule php4_module "E:/Program
 Files/EasyPHP/php/php4apache.dll"
AddModule mod_php4.c
خطوط بارگذاری ماژول که به آپاچی امکان کار با PHP4 را می‌دهند.
    AddType application/x-httpd-php
 .phtml .pwml .php3 
.php4 .php .php2 .inc
پسوندهای فایلی را مشخص می‌کند که باید توسط PHP پردازش شوند

8.1.3.4. اداره MySQL با استفاده از PhpMyAdmin

در صفحهٔ مدیریت EasyPhp، روی دکمهٔ PhpMyAdmin کلیک کنید:

Image

فهرست کشویی زیر Accueil به شما امکان می‌دهد مشاهده کنید
پایگاه‌های داده.
عدد داخل پرانتز تعداد جداول است. اگر شما
اگر یک پایگاه داده را انتخاب کنیم، جداول آن نمایش داده می‌شوند:

صفحه وب تعدادی عملیات روی پایگاه داده ارائه می‌دهد:

Image

اگر روی لینک Afficher از user کلیک کنید:

Image

در اینجا تنها یک کاربر وجود دارد: root، که مدیر MySQL است. با دنبال کردن لینک Modifier، می‌توانید رمز عبور او را که در حال حاضر خالی است، تغییر دهید – کاری که برای یک مدیر توصیه نمی‌شود.

دیگر در مورد PhpMyAdmin حرفی نمی‌زنیم، که نرم‌افزاری غنی از امکانات است و شایسته بحثی چند صفحه‌ای است.

8.1.4. PHP

ما دیدیم که چگونه می‌توان PHP را از طریق برنامه EasyPhp به دست آورد. برای دریافت مستقیم PHP، به وب‌سایت http://www.php.net بروید.

PHP محدود به استفاده در وب نیست. می‌توان از آن به‌عنوان یک زبان اسکریپتی در ویندوز استفاده کرد. اسکریپت زیر را ایجاد کرده و آن را با نام date.php ذخیره کنید:

<?
   // اسکریپت PHP نمایش‌دهنده زمان
  $maintenant=date("j/m/y, H:i:s",time());
  echo "Nous sommes le $maintenant";
?>

در یک پنجره DOS، به دایرکتوری حاوی date.php بروید و آن را اجرا کنید:

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 از قبل نصب شده باشد. اگر این مرورگر موجود باشد، Active Perl آن را پیکربندی می‌کند تا اسکریپت‌های PERL را در صفحات HTML بپذیرد؛ این اسکریپت‌ها توسط خود IE در سمت کلاینت اجرا خواهند شد. وب‌سایت Active Perl در URL http://www.activestate.comA قرار دارد. هنگام نصب، PERL در دایرکتوری‌ای به نام <perl> نصب خواهد شد. ساختار دایرکتوری آن به شرح زیر است:

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 در <perl>\bin قرار دارد. پرل یک زبان اسکریپتی است که روی ویندوز و یونیکس اجرا می‌شود. این زبان همچنین در برنامه‌نویسی WEB استفاده می‌شود. بیایید اولین اسکریپت خود را بنویسیم:

# PERL اسکریپت نمایش‌دهنده زمان

#ماژول‌ها
use strict;

# برنامه
my ($secondes,$minutes,$heure)=localtime(time);
print "Il est $heure:$minutes:$secondes\n";

این اسکریپت را در فایلی به نام heure.pl ذخیره کنید. یک پنجره DOS را باز کنید، به دایرکتوری حاوی اسکریپت بروید و آن را اجرا کنید:

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

8.1.6. VBScript، JavaScript، PerlScript

این‌ها زبان‌های اسکریپتی برای ویندوز هستند. آن‌ها می‌توانند در محیط‌های مختلفی مانند

  • میزبان اسکریپت ویندوز برای استفاده مستقیم در ویندوز، به‌ویژه برای نوشتن اسکریپت‌های مدیریت سیستم
  • Internet Explorer. سپس در صفحات HTML استفاده می‌شود که به آن‌ها درجه‌ای از تعاملی بودن می‌افزاید که با استفاده از HTML به‌تنهایی قابل دستیابی نیست.
  • سرور اطلاعات اینترنتی (IIS)، سرور وب مایکروسافت بر روی NT/2000، و معادل آن، سرور وب شخصی (PWS)، بر روی Win9x. در این مورد، VBScript برای برنامه‌نویسی وب سمت سرور استفاده می‌شود، فناوری‌ای که مایکروسافت آن را ASP (صفحه‌های پویا سرور) می‌نامد.

فایل نصب را از URL دانلود کنید: http://msdn.microsoft.com/scripting و پیوندهای Windows Script را دنبال کنید. موارد زیر نصب می‌شوند:

  • کانتینر Windows Scripting Host، که امکان استفاده از زبان‌های اسکریپت‌نویسی مختلف مانند VBScript و JavaScript و همچنین زبان‌های دیگری مانند PerlScript که همراه با Active Perl ارائه می‌شود را فراهم می‌کند.
  • یک مفسر VBscript
  • یک تفسیرگر جاوااسکریپت

بیایید چند تست سریع انجام دهیم. بیایید برنامه زیر را با vbscript بنویسیم:

'یک کلاس
class personne
  Dim nom
  Dim age
End class

' ایجاد یک شیء شخص
Set p1=new personne
With p1
  .nom="dupont"
  .age=18
End With

'نمایش ویژگی‌های شخص p1
With p1
  wscript.echo "nom=" & .nom
  wscript.echo "age=" & .age
End With

این برنامه از اشیاء استفاده می‌کند. بیایید آن را objets.vbs بنامیم (پسوند «vbs» نشان‌دهنده یک فایل VBScript است). به دایرکتوری محل قرارگیری آن بروید و آن را اجرا کنید:

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

اکنون بیایید برنامه جاوااسکریپت زیر را که از آرایه‌ها استفاده می‌کند، بنویسیم:

// آرایه در یک واریانت
// آرایه خالی
tableau=new Array();
affiche(tableau);
// آرایه به‌طور پویا رشد می‌کند
for(i=0;i<3;i++){
  tableau.push(i*10);
}
//نمایش یک آرایه
affiche(tableau);
//دوباره
for(i=3;i<6;i++){
  tableau.push(i*10);
}
affiche(tableau);

// جدولهای چندبعدی
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);
  }//برای j
}// برای i
affiche2(tableau2);

// پایان
WScript.quit(0);

// ---------------------------------------------------------
function affiche(tableau){
  // نمایش آرایه
  for(i=0;i<tableau.length;i++){
    WScript.echo("tableau[" + i + "]=" + tableau[i]);
  }//برای
}//تابع

// ---------------------------------------------------------
function affiche2(tableau){
   //نمایش جدول
  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
}//تابع

این برنامه از آرایه‌ها استفاده می‌کند. بیایید آن را tableaux.js بنامیم (پسوند «js» نشان‌دهنده یک فایل جاوااسکریپت است). به دایرکتوری محل قرارگیری آن بروید و آن را اجرا کنید:

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

یک مثال نهایی در PerlScript برای جمع‌بندی. برای دسترسی به PerlScript باید Active Perl را نصب کرده باشید.

<job id="PERL1">
  <script language="PerlScript">
       # پِرل کلاسیک
    %dico=("maurice"=>"juliette","philippe"=>"marianne");
    @cles= keys %dico;
    for ($i=0;$i<=$#کلیدها؛$i++){
        $cle=$cles[$i];
      $valeur=$dico{$cle};
        $WScript->echo ("clé=".$cle.", valeur=".$valeur);
    }
     # PerlScript با استفاده از اشیاء 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>

این برنامه نحوهٔ ساخت و استفاده از دو فرهنگ لغت را نشان می‌دهد: یکی به سبک کلاسیک پرل و دیگری با استفاده از شیء Dictionary در Windows Script Scripting. بیایید این کد را در فایل dico.wsf ذخیره کنیم (wsf پسوند فایل‌های Windows Script است). بیایید به پوشه‌ای که این برنامه در آن قرار دارد برویم و آن را اجرا کنیم:

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 می‌تواند از اشیاء موجود در کانتینری که در آن در حال اجراست استفاده کند. در این مورد، این‌ها اشیاء کانتینر Windows Script بودند. در زمینه برنامه‌نویسی وب، اسکریپت‌های VBscript، اسکریپت‌های JavaScript و PerlScript می‌توانند یا درون مرورگر IE اجرا شوند، یا روی یک سرور PWS یا IIS. اگر اسکریپت تا حدی پیچیده باشد، ممکن است بهتر باشد آن را خارج از محیط وب، در کانتینر Windows Script همانطور که قبلاً بحث شد، آزمایش کنید. این کار فقط به شما امکان می‌دهد تا آن بخش‌های اسکریپت را که از اشیاء مخصوص مرورگر یا سرور استفاده نمی‌کنند، آزمایش کنید. حتی با وجود این محدودیت، این گزینه همچنان مفید است زیرا عیب‌یابی اسکریپت‌های در حال اجرا در وب‌سرورها یا مرورگرها عموماً چندان عملی نیست.

8.1.7. JAVA

جاوا در URL در دسترس است: http://www.sun.com و در ساختار دایرکتوری‌ای نصب شده است که آن را <java> می‌نامیم و شامل اجزای زیر است:

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» فایل‌های javac.exe (کامپایلر جاوا) و java.exe (ماشین مجازی جاوا) را خواهید یافت. می‌توانید تست‌های زیر را انجام دهید:

  1. اسکریپت زیر را بنویسید:
//برنامهٔ جاوا که زمان را نمایش می‌دهد

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

public class heure{
  public static void main(String arg[]){
     //بازیابی تاریخ و زمان
     Date maintenant=new Date();
      //نمایش
     System.out.println("Il est "+maintenant.getHours()+
        ":"+maintenant.getMinutes()+":"+maintenant.getSeconds());
  }//اصلی
}//کلاس
  1. این برنامه را با نام heure.java ذخیره کنید. یک پنجره DOS باز کنید. به دایرکتوری حاوی فایل heure.java بروید و آن را کامپایل کنید:
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.

در دستور بالا، باید c:\jdk1.3\bin\javac را با مسیر دقیق کامپایلر javac.exe جایگزین کنید. در همان دایرکتوری heure.java، باید فایلی به نام heure.class پیدا کنید که برنامه‌ای است که اکنون توسط ماشین مجازی java.exe اجرا خواهد شد.

  1. برنامه را اجرا کنید:
D:\data\java\essais>c:\jdk1.3\bin\java heure
Il est 10:44:2

8.1.8. سرور آپاچی

ما دیدیم که سرور آپاچی را می‌توان از طریق برنامه EasyPhp به دست آورد. برای دانلود مستقیم آن، به وب‌سایت آپاچی بروید: http://www.apache.org. نصب، ساختار دایرکتوری‌ای ایجاد می‌کند که شامل تمام فایل‌های مورد نیاز برای سرور است. بیایید این دایرکتوری را <apache> بنامیم. این دایرکتوری ساختار مشابهی با موارد زیر دارد:

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
پوشهٔ فایل‌های پیکربندی آپاچی
logs
پوشهٔ فایل‌های لاگ آپاچی
bin
فایل‌های اجرایی آپاچی

8.1.8.1. Configuration

پوشه <Apache>\conf شامل فایل‌های زیر است: httpd.conf، srm.conf، access.conf. در جدیدترین نسخه‌های آپاچی، این سه فایل در httpd.conf ادغام شده‌اند. ما پیش از این نکات کلیدی این فایل پیکربندی را تشریح کرده‌ایم. در مثال‌های زیر، از نسخه EasyPhp آپاچی برای آزمایش استفاده شده و در نتیجه فایل پیکربندی آن. در این فایل، DocumentRoot که ریشه ساختار دایرکتوری صفحات وب را مشخص می‌کند، e:\program files\easyphp\www است.

8.1.8.2. لینک به PHP – آپاچی

برای آزمایش این موضوع، یک فایل به نام intro.php ایجاد کنید که فقط شامل خط زیر باشد:

<? phpinfo() ?>

و آن را در دایرکتوری ریشهٔ سرور آپاچی (DocumentRoot بالا) قرار دهید. فایل URL را در http://localhost/intro.php درخواست کنید. شما باید فهرستی از اطلاعات را مشاهده کنید:

Image

اسکریپت زیر PHP زمان را نمایش می‌دهد. ما قبلاً با آن مواجه شده‌ایم:

<?php
   //زمان: تعداد میلی‌ثانیه‌ها از ۱ ژانویه ۱۹۷۰
   // "قالب نمایش تاریخ و زمان"
   // d: روز (۲ رقم)
   // m: ماه دو رقمی
   // y: سال (۲ رقم)
   // H: ساعت 0.23
   // i: دقیقه
   // s: ثانیه‌ها
  print "Nous sommes le " . date("d/m/y H:i:s",time());
?>

بیایید این فایل متنی را در دایرکتوری ریشهٔ سرور آپاچی (DocumentRoot) قرار دهیم و آن را date.php نامگذاری کنیم. بیایید با استفاده از یک مرورگر به http://localhost/date.php دسترسی پیدا کنیم. صفحه زیر را مشاهده می‌کنیم:

Image

8.1.8.3. لینک PERL-APACHE

این با استفاده از یک خط به شکل زیر ایجاد می‌شود: ScriptAlias /cgi-bin/ "E:/Program Files/EasyPHP/cgi-bin/" از فایل <apache>\conf\httpd.conf. نحو آن به صورت زیر است: ScriptAlias /cgi-bin/ "<cgi-bin>"، که در آن <cgi-bin> پوشه‌ای است که اسکریپت‌های CGI می‌توانند در آن قرار گیرند. CGI (رابط درگاه مشترک) استانداردی برای ارتباط بین سرور WEB و برنامه‌ها است. یک کلاینت یک صفحه پویا را از وب‌سرور c.a.d درخواست می‌کند – صفحه‌ای که توسط یک برنامه تولید می‌شود. بنابراین سرور باید به یک برنامه دستور دهد تا صفحه را تولید کند. CGI تعامل بین سرور و برنامه را تعریف می‌کند، به‌ویژه نحوه انتقال اطلاعات بین این دو واحد.

در صورت لزوم، خط ScriptAlias /cgi-bin/ "<cgi-bin>" را اصلاح کرده و سرور آپاچی را مجدداً راه‌اندازی کنید. سپس تست زیر را انجام دهید:

  1. اسکریپت را بنویسید:
#!c:\perl\bin\perl.exe

# PERL اسکریپت نمایش زمان

#ماژول‌ها
use strict;

#برنامه
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. این اسکریپت را در <cgi-bin>\heure.pl قرار دهید، جایی که <cgi-bin> پوشه‌ای است که قادر به نگهداری اسکریپت‌های CGI می‌باشد (به httpd.conf مراجعه کنید). خط اول، #!c:\perl\bin\perl.exe، مسیر فایل اجرایی perl.exe را مشخص می‌کند. در صورت لزوم آن را تغییر دهید.
  2. اگر هنوز Apache را راه‌اندازی نکرده‌اید، آن را راه‌اندازی کنید.
  3. با استفاده از یک مرورگر وب به فایل URL در http://localhost/cgi-bin/heure.pl دسترسی پیدا کنید. صفحه زیر نمایش داده می‌شود:

Image

8.1.9. سرور PWS

8.1.9.1. Installation

سرور PWS (سرور وب شخصی) نسخه‌ای شخصی از سرور IIS مایکروسافت (سرور اطلاعات اینترنتی) است. سرور دوم بر روی سیستم‌های NT و ۲۰۰۰ در دسترس است. در سیستم‌های Win9x، PWS معمولاً در بستهٔ نصب Internet Explorer گنجانده شده است. با این حال، به‌صورت پیش‌فرض نصب نمی‌شود. شما باید نصب سفارشی IE را انجام داده و نصب PWS را مشخص کنید. این برنامه همچنین در بستهٔ Option Pack 4.0 NT برای ویندوز 95 موجود است.

8.1.9.2. آزمایش‌های اولیه

دایرکتوری ریشه برای صفحات وب روی سرور PWS درایو:\inetpub\wwwroot است، که در آن درایو همان درایوی است که PWS را روی آن نصب کرده‌اید. از این پس فرض می‌کنیم این درایو D است. بنابراین، URL http://machine/rep1/page1.html به فایل d:\inetpub\wwwroot\rep1\page1.html مربوط می‌شود. سرور PWS هر فایلی با پسوند .asp (صفحات سرور پویا) را به عنوان اسکریپتی در نظر می‌گیرد که باید برای تولید یک صفحه HTML اجرا شود.

PWS به‌طور پیش‌فرض روی پورت ۸۰ اجرا می‌شود. وب‌سرور آپاچی نیز همین‌طور... بنابراین اگر هر دو سرور را راه‌اندازی کرده‌اید، برای کار با PWS باید آپاچی را متوقف کنید. راه حل دیگر این است که آپاچی را طوری پیکربندی کنید که روی پورت متفاوتی اجرا شود. بنابراین، در فایل پیکربندی آپاچی httpd.conf، خط «Port 80» را با «Port 81» جایگزین کنید؛ اکنون آپاچی روی پورت 81 اجرا خواهد شد و می‌توان همزمان با PWS از آن استفاده کرد. اگر PWS راه‌اندازی شده باشد و شما http://localhost را در URL درخواست کنید، صفحه‌ای مشابه شکل زیر را مشاهده خواهید کرد:

Image

8.1.9.3. لینک PHP - PWS

  1. در زیر یک فایل .reg برای ویرایش رجیستری قرار دارد. برای ویرایش رجیستری، روی این فایل دوبار کلیک کنید. در اینجا، dll مورد نیاز در d:\php4 در کنار فایل اجرایی PHP قرار دارد. در صورت لزوم آن را ویرایش کنید. کاراکترهای \ باید در مسیر DLL به صورت جفتی نوشته شوند.
REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map]
".php"="d:\\php4\\php4isapi.dll"
  1. دستگاه را مجدداً راه‌اندازی کنید تا تغییرات رجیستری اعمال شوند.
  1. یک پوشه «php» در داخل d:\inetpub\wwwroot که دایرکتوری ریشه سرور PWS است، ایجاد کنید. پس از انجام این کار، PWS را باز کرده و به زبانه «Advanced» بروید. روی دکمه «Add» کلیک کنید تا یک پوشه مجازی ایجاد شود:
Répertoire/Parcourir : d:\inetpub\wwwroot\php
Alias : php
Cocher la case exécuter.
  1. تغییرات را تأیید کرده و PWS را مجدداً راه‌اندازی کنید. فایل intro.php را که تنها شامل خط زیر است، در d:\inetpub\wwwroot\php قرار دهید:
<? phpinfo() ?>
  1. فایل URL (http://localhost/php/intro.php) را از سرور PWS درخواست کنید. شما باید فهرست اطلاعات PHP را که از قبل توسط آپاچی نمایش داده شده است، مشاهده کنید.

8.1.10. تام‌کت: سرولت‌های جاوا و صفحات JSP (Java Server Pages)

تامکت یک وب‌سرور است که امکان تولید صفحات HTML را با استفاده از سرولت‌ها (برنامه‌های جاوا که توسط وب‌سرور اجرا می‌شوند) یا صفحات JSP (Java Server Pages) فراهم می‌کند، که کد جاوا و کد HTML را ترکیب می‌کنند. این معادل ASP است (صفحه‌های سرور پویا) در سرور IIS/PWS مایکروسافت، که در آن کد VBScript یا جاوااسکریپت با کد HTML ترکیب می‌شود.

8.1.10.1. Installation

Tomcat در URL در دسترس است: http://jakarta.apache.org. می‌توانید یک فایل نصب .exe دانلود کنید. وقتی این برنامه را اجرا می‌کنید، ابتدا از شما می‌پرسد که کدام JDK را استفاده کند. این به این دلیل است که Tomcat برای نصب خود و سپس برای کامپایل و اجرای servletهای جاوا به یک JDK نیاز دارد. بنابراین باید قبل از نصب Tomcat، یک JDK جاوا نصب شده باشد. جدیدترین JD توصیه می‌شود. نصب، ساختار دایرکتوری <tomcat> را ایجاد خواهد کرد:

Image

این کار صرفاً شامل استخراج این آرشیو در یک پوشه است. یک دایرکتوری انتخاب کنید که مسیر آن فقط شامل نام‌ها باشد و هیچ فاصله‌ای در آن نباشد (مثلاً «Program Files» نباشد)، زیرا در فرآیند نصب Tomcat یک باگ وجود دارد. برای مثال، از C:\tomcat یا D:\tomcat استفاده کنید. بیایید این دایرکتوری را <tomcat> بنامیم. در داخل آن، پوشه‌ای به نام jakarta-tomcat خواهید یافت که ساختار دایرکتوری زیر را در خود دارد:

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

تامکت یک سرور وب است، درست مانند آپاچی یا PWS. برای راه‌اندازی آن، در منوی برنامه‌ها لینک‌هایی وجود دارد:

Start Tomcat
برای راه‌اندازی Tomcat
Stop Tomcat
برای متوقف کردن آن

هنگامی که Tomcat را راه‌اندازی می‌کنید، یک پنجره DOS با محتوای زیر ظاهر می‌شود:

Image

می‌توانید این پنجره DOS را کوچک کنید. تا زمانی که Tomcat در حال اجرا باشد، این پنجره باز خواهد ماند. سپس می‌توانید به تست‌های اولیه بپردازید. سرور وب Tomcat بر روی پورت 8080 اجرا می‌شود. پس از راه‌اندازی Tomcat، یک مرورگر وب باز کرده و به آدرس http://localhost:8080 بروید. باید صفحه زیر را مشاهده کنید:

Image

روی لینک «Servlet Examples» کلیک کنید:

Image

روی لینک Execute از RequestParameters کلیک کنید، سپس روی لینک Source کلیک کنید. این به شما دید اولیه‌ای از اینکه یک سروِلِت جاوا چیست می‌دهد. شما می‌توانید همین کار را با لینک‌های صفحات JSP انجام دهید.

برای متوقف کردن Tomcat، از لینک «Stop Tomcat» در منوی برنامه استفاده کنید.

8.1.11. JBuilder

JBuilder یک محیط توسعهٔ برنامه‌های کاربردی جاوا است. برای ساخت سرولت‌های جاوا که شامل رابط کاربری گرافیکی نیستند، داشتن چنین محیطی ضروری نیست. یک ویرایشگر متن و یک JDK این کار را انجام می‌دهند. با این حال، JBuilder چند مزیت نسبت به روش قبلی ارائه می‌دهد:

  • آسانی عیب‌یابی: کامپایلر خطوط اشتباه در برنامه را برجسته می‌کند و پیمایش به آن‌ها آسان است
  • پیشنهادات کد: هنگام استفاده از یک شیء جاوا، JBuilder فهرستی از ویژگی‌ها و متدهای آن را به صورت inline نمایش می‌دهد. این قابلیت بسیار مفید است، زیرا اکثر اشیاء جاوا دارای تعداد زیادی ویژگی و متد هستند که به خاطر سپردن آن‌ها دشوار است.

می‌توانید JBuilder را در وب‌سایت http://www.borland.com/jbuilder پیدا کنید. برای دریافت نرم‌افزار باید یک فرم را پر کنید. یک کلید فعال‌سازی از طریق ایمیل برای شما ارسال می‌شود. برای نصب JBuilder 7، به عنوان مثال، مراحل زیر طی شد:

  • سه فایل ZIP دانلود شدند: یکی برای برنامه، یکی برای مستندات و یکی برای مثال‌ها. هر یک از این فایل‌های ZIP لینک جداگانه‌ای در وب‌سایت JBuilder دارد.
  • ابتدا نرم‌افزار، سپس مستندات و در نهایت مثال‌ها نصب شدند
  • وقتی برنامه را برای اولین بار اجرا می‌کنید، از شما یک کلید فعال‌سازی خواسته می‌شود: این همان کلیدی است که از طریق ایمیل برای شما ارسال شده است. در نسخه ۷، این کلید در واقع کل محتویات یک فایل متنی است که می‌توانید آن را، برای مثال، در پوشه نصب JB7 قرار دهید. هنگامی که کلید درخواست شد، شما فایل مربوطه را انتخاب می‌کنید. پس از انجام این کار، دیگر از شما کلید خواسته نخواهد شد.

اگر می‌خواهید از JBuilder برای ساخت سرولت‌های جاوا استفاده کنید، چند مرحله پیکربندی مفید وجود دارد که باید انجام دهید. نسخه موسوم به «JBuilder Personal» یک نسخه ساده‌شده است که توجه داشته باشید، شامل تمام کلاس‌های مورد نیاز برای توسعه وب جاوا نیست. می‌توانید JBuilder را برای استفاده از کتابخانه‌های کلاسی ارائه‌شده توسط Tomcat پیکربندی کنید. مراحل زیر را دنبال کنید:

  • JBuilder را اجرا کنید

Image

  • گزینه Tools/Configure JDKs را فعال کنید

Image

در بخش تنظیمات JDK در بالا، فیلد Name به طور معمول باید حاوی «JDK 1.3.1» باشد. اگر نسخه جدیدتری از JDK دارید، از دکمه Change برای مشخص کردن مسیر نصب آن استفاده کنید. در بالا، ما مسیر E:\Program Files\jdk14 را مشخص کرده‌ایم، جایی که نسخه‌ای از JDK 1.4 نصب شده بود. از این پس، JBuilder از این JDK برای کامپایل‌ها و اجراهای خود استفاده خواهد کرد. در بخش (Class, Source, Documentation)، فهرستی از تمام کتابخانه‌های کلاسی که توسط JBuilder اسکن خواهند شد، وجود دارد؛ در این مورد، کلاس‌های مربوط به JDK 1.4. کلاس‌های موجود در آن برای توسعه وب جاوا کافی نیستند. برای افزودن کتابخانه‌های کلاس بیشتر، از دکمه «Add» استفاده کنید و فایل‌های .jar اضافی مورد نظر خود را انتخاب کنید. فایل‌های .jar کتابخانه‌های کلاس هستند. Tomcat 4.x شامل تمام کتابخانه‌های کلاسی مورد نیاز برای توسعه وب است. این فایل‌ها در <tomcat>\common\lib قرار دارند، که در آن <tomcat> مسیر نصب Tomcat است:

Image

با استفاده از دکمه «Add»، این کتابخانه‌ها را یکی‌یکی به فهرست کتابخانه‌های اسکن‌شده توسط JBuilder اضافه خواهیم کرد:

Image

از این پس، می‌توانید برنامه‌های جاوایی را که با استاندارد J2EE مطابقت دارند، از جمله سرولیت‌های جاوا، کامپایل کنید. JBuilder صرفاً برای کامپایل استفاده می‌شود؛ اجرای برنامه پس از آن توسط Tomcat انجام می‌شود، همانطور که در دوره توضیح داده شده است.

8.2. کد منبع برنامه

8.2.1. کلاینت عمومی TCP

بسیاری از سرویس‌هایی که در روزهای اولیه اینترنت ایجاد شده‌اند، بر اساس مدل سرور اکو که قبلاً مطالعه شد، عمل می‌کنند: ارتباط کلاینت-سرور از طریق تبادل خطوط متن انجام می‌شود. ما قصد داریم یک کلاینت عمومی TCP بنویسیم که به شکل زیر اجرا خواهد شد: java cltTCPgenerique server port

این کلاینت TCP به پورت port روی سرور serveur متصل خواهد شد. پس از انجام این کار، دو تِرد ایجاد خواهد کرد:

  1. یک نخ مسئول خواندن دستورات تایپ‌شده روی صفحه‌کلید و ارسال آن‌ها به سرور
  2. یک تِرد مسئول خواندن پاسخ‌های سرور و نمایش آن‌ها روی صفحه

چرا دو نخ؟ هر سرویس TCP-IP پروتکل خاص خود را دارد و گاهی اوقات ممکن است شرایط زیر پیش بیاید:

  • کلاینت باید قبل از دریافت پاسخ، چندین خط متن ارسال کند
  • پاسخ یک سرور ممکن است شامل چندین خط متن باشد

بنابراین، حلقه مربوط به ارسال یک خط به سرور و دریافت یک خط از سرور همیشه مناسب نیست. بنابراین ما دو حلقه مجزا ایجاد خواهیم کرد:

  • یک حلقه برای خواندن دستورات تایپ‌شده روی صفحه‌کلید جهت ارسال به سرور. کاربر پایان دستورات را با کلمه کلیدی fin اعلام خواهد کرد.
  • یک حلقه برای دریافت و نمایش پاسخ‌ها از سرور. این یک حلقه بی‌نهایت خواهد بود که تنها زمانی متوقف می‌شود که سرور اتصال شبکه را قطع کند یا کاربر فرمان fin را تایپ کند.

برای جدا نگه داشتن این دو حلقه، به دو نخ (thread) مستقل نیاز داریم. بیایید نگاهی به یک مثال اجرایی بیندازیم که در آن کلاینت عمومی TCP ما به سرویسی به نام SMTP (پروتکل انتقال SendMail) متصل می‌شود. این سرویس مسئول مسیریابی ایمیل به گیرندگان آن است. این سرویس بر روی پورت ۲۵ کار می‌کند و از یک پروتکل گفتگوی مبتنی بر متن استفاده می‌کند.

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]

بیایید این مبادلات کلاینت-سرور را تحلیل کنیم:

  • سرویس SMTP هنگام اتصال یک کلاینت به آن، یک پیام خوش‌آمدگویی ارسال می‌کند:
<-- 220 istia.univ-angers.fr ESMTP Sendmail 8.11.6/8.9.3; Mon, 13 May 2002 08:37:26 +0200
  • برخی سرویس‌ها دارای دستوری هستند، help، که اطلاعاتی در مورد دستورات قابل استفاده با سرویس ارائه می‌دهد. در اینجا چنین نیست. دستورات SMTP که در مثال استفاده شده‌اند به شرح زیر است:
    • mail from: expéditeur، برای مشخص کردن آدرس ایمیل فرستنده
    • rcpt to: destinataire، برای مشخص کردن آدرس ایمیل گیرنده پیام. اگر گیرندگان متعددی وجود داشته باشند، دستور rcpt to: به تعداد لازم برای هر گیرنده تکرار می‌شود.
    • data، که به سرور SMTP سیگنال می‌دهد که پیام آماده ارسال است. همانطور که در پاسخ سرور نشان داده شده است، این شامل مجموعه‌ای از خطوط است که با خطی حاوی فقط یک نقطه پایان می‌یابد. یک پیام ممکن است دارای سربرگ‌هایی باشد که با یک خط خالی از بدنه پیام جدا شده‌اند. در مثال ما، با استفاده از کلمه کلیدی Subject: یک موضوع را گنجانده‌ایم:
  • پس از ارسال پیام، می‌توانید با استفاده از دستور 'quit' به سرور اطلاع دهید که کارتان تمام شده است. سپس سرور اتصال شبکه را قطع می‌کند. رشتهٔ خواندن می‌تواند این رویداد را تشخیص داده و متوقف شود.
  • سپس کاربر برای متوقف کردن نخ خواندن دستورات تایپ‌شده روی صفحه‌کلید، کلید 'end' را فشار می‌دهد.

اگر ایمیل دریافتی را بررسی کنیم، موارد زیر را مشاهده می‌کنیم (آوت‌لوک):

Image

توجه داشته باشید که سرویس SMTP نمی‌تواند تشخیص دهد که فرستنده معتبر است یا خیر. بنابراین، فیلد from در یک پیام هرگز قابل اعتماد نیست. در این مورد، فرستنده «machin@univ-angers.fr» وجود نداشت.

این کلاینت عمومی TCP می‌تواند به ما کمک کند تا پروتکل ارتباطی مورد استفاده توسط سرویس‌های اینترنتی را شناسایی کرده و از آنجا کلاس‌های تخصصی برای کلاینت‌های این سرویس‌ها بسازیم. بیایید پروتکل ارتباطی سرویس POP (پروتکل دفتر پستی) را بررسی کنیم که به کاربران اجازه می‌دهد ایمیل‌های ذخیره‌شده خود را از روی سرور بازیابی کنند. این پروتکل بر روی پورت ۱۱۰ کار می‌کند.

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]

فرمان‌های اصلی به شرح زیر هستند:

  • user login، جایی که مشخصات ورود خود را برای دستگاه میزبان ایمیل‌هایتان وارد می‌کنید
  • pass password، که در آن رمز عبور مرتبط با ورود قبلی را وارد می‌کنید
  • list، برای دریافت فهرست پیام‌ها در قالب: شماره، اندازه به بایت
  • retr i، برای خواندن پیام شماره i
  • quit، برای پایان دادن به جلسه.

اکنون بیایید به پروتکل ارتباط بین یک کلاینت و یک سرور وب، که معمولاً روی پورت ۸۰ اجرا می‌شود، نگاهی بیندازیم:

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]

یک کلاینت وب دستورات خود را بر اساس الگوی زیر به سرور ارسال می‌کند:

commande1
commande2
...
commanden
[ligne vide]

سرور وب تنها پس از دریافت خط خالی پاسخ می‌دهد. در این مثال، ما فقط از یک دستور استفاده کرده‌ایم:

GET /index.html HTTP/1.0

که از سرور می‌خواهد URL /index.html را ارسال کند و نشان می‌دهد که از نسخه ۱.۰ پروتکل HTTP استفاده می‌کند. جدیدترین نسخه این پروتکل ۱.۱ است. این مثال نشان می‌دهد که سرور با بازگرداندن محتویات فایل index.html پاسخ داده و سپس اتصال را قطع کرده است، همان‌طور که می‌بینیم نخ خواندن پاسخ‌ها متوقف شده است. وب‌سرور قبل از ارسال محتویات فایل index.html، مجموعه‌ای از سربرگ‌ها را ارسال کرد که با یک خط خالی پایان می‌یابد:

<-- 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> اولین خط فایل /index.html است. خطوط قبلی به عنوان سرآیندهای HTTP (پروتکل انتقال HyperText) شناخته می‌شوند. در اینجا وارد جزئیات این سرآیندها نمی‌شویم، اما شایان ذکر است که کلاینت عمومی ما به آن‌ها دسترسی می‌دهد که ممکن است برای درک آن‌ها مفید باشد. برای مثال، خط اول را در نظر بگیرید:

<-- HTTP/1.1 200 OK

نشان می‌دهد که سرور وب تماس‌گرفته شده از پروتکل HTTP/1.1 پشتیبانی می‌کند و با موفقیت فایل درخواستی (200 OK) را پیدا کرده است، که در آن 200 یک کد پاسخ HTTP است. خطوط

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

به کلاینت بگویید که ۱۱٬۲۵۱ بایت دریافت خواهد کرد که نمایانگر متن در HTML (زبان نشانه‌گذاری HyperText) است و پس از اتمام انتقال، اتصال بسته خواهد شد.

پس در اینجا یک کلاینت TCP بسیار کاربردی داریم. این برنامه بی‌شک کمتر از برنامه رسمی telnet انجام می‌دهد، اما نوشتن آن به دست خودمان جالب بود. برنامه کلی کلاینت TCP به شرح زیر است:

// پکیج‌های وارداتی
import java.io.*;
import java.net.*;

public class clientTCPgenerique{

    // ویژگی‌های یک سرویس را به‌عنوان پارامتر در قالب می‌گیرد
     // پورت سرور
     //به سرویس متصل می‌شود
     // یک نخ ایجاد می‌کند تا دستورات تایپ‌شده روی صفحه‌کلید را بخواند
     // این‌ها به سرور ارسال خواهند شد
     // یک نخ ایجاد می‌کند تا پاسخ‌ها را از سرور بخواند
     //این‌ها روی صفحه نمایش داده می‌شوند
     //کل فرآیند زمانی پایان می‌یابد که دستور «end» تایپ شود

   // متغیر نمونه
  private static Socket client;

    public static void main(String[] args){

         // دستور زبان
        final String syntaxe="pg serveur port";

         // تعداد آرگومان‌ها
        if(args.length != 2)
            erreur(syntaxe,1);

         // توجه کنید نام سرور
        String serveur=args[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;
         //ممکن است مشکلاتی وجود داشته باشد
        try{
             // اتصال به سرویس
            client=new Socket(serveur,port);
        }catch(Exception ex){
             // خطا
            erreur("Impossible de se connecter au service ("+ serveur
                +","+port+"), erreur : "+ex.getMessage(),3);
             // پایان
            return;
        }//catch

         // رشته‌های خواندن/نوشتن ایجاد می‌شوند
    new ClientSend(client).start();
    new ClientReceive(client).start();

         //پایان نخ اصلی
        return;
    }// اصلی

     //نمایش خطاها
    public static void erreur(String msg, int exitCode){
         // نمایش خطا
        System.err.println(msg);
         //خاتمه با خطا
        System.exit(exitCode);
    }//خطا
}//کلاس  

class ClientSend extends Thread {
    // کلاس مسئول خواندن دستورات وارد شده از طریق صفحه‌کلید
     // و ارسال آن‌ها به یک سرور از طریق یک کلاینت TCP که به‌عنوان پارامتر ارسال شده است

    private Socket client;    // کلاینت TCP

     // سازنده
    public ClientSend(Socket client){
         //توجه به کلاینت TCP
        this.client=client;
    }//

     // متد Runِ نخ
    public void run(){

        // داده‌های محلی
        PrintWriter OUT=null;            //جریان نوشتن شبکه
    BufferedReader IN=null;        //جریان صفحه‌کلید
        String commande=null;            // دستور خوانده شده از صفحه‌کلید

         // پردازش خطا
        try{
             //ایجاد جریان نوشتن شبکه
            OUT=new PrintWriter(client.getOutputStream(),true);
      // ایجاد جریان ورودی صفحه‌کلید
      IN=new BufferedReader(new InputStreamReader(System.in));
            //حلقه ورودی و ارسال فرمان
            System.out.println("Commandes : ");
            while(true){
                 //خواندن دستوری که روی صفحه‌کلید تایپ شده است
                commande=IN.readLine().trim();
                 // تمام شد؟
                if (commande.toLowerCase().equals("fin")) break;
                //ارسال فرمان به سرور
                OUT.println(commande);
                 // دستور بعدی
            }//در حالی که
        }catch(Exception ex){
             //خطا
            System.err.println("Envoi : L'erreur suivante s'est produite : " + ex.getMessage());
        }//گرفت
         //پایان – بستن استریم‌ها
        try{
            OUT.close();client.close();
        }catch(Exception ex){}
         // نشان‌دهنده پایان نخ
        System.out.println("[Envoi : fin du thread d'envoi des commandes au serveur]");
    }//اجرا
}//کلاس

class ClientReceive extends Thread{
    //کلاسی که مسئول خواندن خطوط متنی است که برای یک 
     // کلاینت TCP به‌عنوان پارامتر ارسال شده است

    private Socket client;    // کلاینت TCP

     // سازنده
    public ClientReceive(Socket client){
         // توجه شود که کلاینت TCP
        this.client=client;
    }//

     // متد Runِ نخ
    public void run(){

        // داده‌های محلی
        BufferedReader IN=null;        //جریان خواندن شبکه
        String réponse=null;        // پاسخ سرور

         // مدیریت خطا
        try{
             //ایجاد جریان خواندن شبکه
            IN=new BufferedReader(new InputStreamReader(client.getInputStream()));
            //حلقه برای خواندن خطوط متن از جریان IN
            while(true){
                 // خواندن جریان شبکه
                réponse=IN.readLine();
                 //آیا جریان بسته است؟
                if(réponse==null) break;
                //نمایش
                System.out.println("<-- "+réponse);
            }//در حالی که
        }catch(Exception ex){
            //خطا
            System.err.println("Réception : L'erreur suivante s'est produite : " + ex.getMessage());
        }//گرفتن
         //پایان – جریان‌ها بسته شده‌اند
        try{
            IN.close();client.close();
        }catch(Exception ex){}
         // نشان‌دهنده پایان نخ
        System.out.println("[Réception : fin du thread de lecture des réponses du serveur]");
    }//اجرا
}//کلاس

8.2.2. سرور عمومی TCP

اکنون به یک سرور نگاه می‌کنیم

  • که دستورات ارسال‌شده توسط کلاینت‌های خود را روی صفحه نمایش می‌دهد
  • و در پاسخ، خطوط متنی را که کاربر از طریق صفحه‌کلید وارد کرده است، برای آن‌ها ارسال می‌کند. بنابراین این کاربر است که نقش سرور را ایفا می‌کند.

برنامه با استفاده از دستور زیر اجرا می‌شود: java serveurTCPgenerique portEcoute، که در آن portEcoute پورتی است که کلاینت‌ها باید به آن متصل شوند. سرویس کلاینت توسط دو نخ (thread) مدیریت خواهد شد:

  • یک تِرد که منحصراً به خواندن خطوط متنی ارسال‌شده توسط کلاینت اختصاص دارد
  • یک تِرد اختصاصی که صرفاً به خواندن پاسخ‌های تایپ‌شده توسط کاربر می‌پردازد. این تِرد با استفاده از دستور 'fin' سیگنال پایان اتصال با کلاینت را ارسال می‌کند.

سرور برای هر کلاینت دو تِرد ایجاد می‌کند. اگر n کلاینت وجود داشته باشد، در یک زمان 2n تِرد فعال خواهند بود. خودِ سرور هرگز متوقف نمی‌شود، مگر اینکه کاربر کلیدهای Ctrl-C را روی صفحه‌کلید فشار دهد. بیایید چند مثال را بررسی کنیم.

سرور روی پورت ۱۰۰ در حال اجرا است و ما از کلاینت عمومی برای ارتباط با آن استفاده می‌کنیم. پنجره کلاینت به این شکل است:

E:\data\serge\MSNET\c#\network\generic TCP client> 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]

خطوطی که با <-- شروع می‌شوند، از سمت سرور به کلاینت ارسال شده‌اند؛ سایر خطوط از سمت کلاینت به سرور ارسال شده‌اند. پنجرهٔ سرور به شرح زیر است:


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]

خطوطی که با <-- شروع می‌شوند، ارسال‌شده از سمت کلاینت به سرور هستند. خطوطی که با N: مشخص شده‌اند، ارسال‌شده از سمت سرور به کلاینت شماره N هستند. سرور بالا هنوز فعال است، در حالی که کلاینت ۱ کارش را تمام کرده است. یک کلاینت دوم برای همان سرور راه‌اندازی می‌شود:


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]

پنجرهٔ سرور سپس به این شکل به نظر می‌رسد:


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

اکنون بیایید با اجرای سرور عمومی خود روی پورت ۸۸، یک سرور وب را شبیه‌سازی کنیم:


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

حالا یک مرورگر را باز کرده و صفحه http://localhost:88/exemple.html را درخواست می‌کنیم. مرورگر سپس به پورت 88 روی ماشین localhost متصل شده و صفحه /exemple.html را درخواست می‌کند:

Image

حال بیایید به پنجرهٔ سرور خود نگاه کنیم:

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

بدین ترتیب می‌توانیم سربرگ‌های HTTP ارسال‌شده توسط مرورگر را مشاهده کنیم. این امر به ما امکان می‌دهد تا پروتکل HTTP را به تدریج کشف کنیم. در مثالی قبلی، ما یک کلاینت وب ساختیم که تنها فرمان واحد GET را ارسال می‌کرد. این کافی بود. در اینجا می‌بینیم که مرورگر اطلاعات بیشتری را برای سرور ارسال می‌کند. هدف از این کار، اطلاع‌رسانی به سرور در مورد نوع کلاینتی است که با آن سر و کار دارد. همچنین می‌بینیم که هدرهای HTTP با یک خط خالی پایان می‌یابند.

بیایید یک پاسخ برای کلاینت خود بسازیم. کاربر پشت کیبورد در این مورد، خود سرور است و می‌تواند پاسخ را به‌صورت دستی بسازد. بیایید پاسخ تولید شده توسط یک وب‌سرور در مثال قبلی را به یاد بیاوریم:

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

بیایید سعی کنیم پاسخ مشابهی ارائه دهیم:

...
<-- 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 شروع می‌شوند، از سرور به کلاینت شماره 2 ارسال می‌شوند. فرمان fin ارتباط بین سرور و کلاینت را خاتمه می‌دهد. در پاسخ خود، ما خود را به سربرگ‌های زیر HTTP محدود کرده‌ایم:

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

ما اندازه فایلی را که قصد ارسال آن را داریم (Content-Length) مشخص نمی‌کنیم، بلکه صرفاً اعلام می‌کنیم که پس از ارسال آن، اتصال را بست خواهیم کرد (Connection: close). این برای مرورگر کافی است. وقتی مرورگر ببیند که اتصال بسته شده است، متوجه می‌شود که پاسخ سرور کامل است و صفحه‌ای را که برایش ارسال شده (HTML) نمایش می‌دهد. این صفحه به شرح زیر است:

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>

سپس کاربر با وارد کردن دستور fin اتصال به کلاینت را قطع می‌کند. مرورگر سپس می‌داند که پاسخ سرور کامل است و می‌تواند آن را نمایش دهد:

Image

اگر، همان‌طور که در بالا نشان داده شده، دستور View/Source را وارد کنیم تا ببینیم مرورگر چه چیزی دریافت کرده است، با خروجی زیر مواجه می‌شویم:

Image

یعنی دقیقاً همان چیزی که از سرور عمومی ارسال شده بود.

کد سرور عمومی TCP به شرح زیر است:

// پکیجها
import java.io.*;
import java.net.*;

public class serveurTCPgenerique{

     // برنامه اصلی
    public static void main (String[] args){

    // روی پورت برای دریافت درخواستهای کلاینت گوش میدهد
     // یک نخ برای خواندن درخواستهای مشتری ایجاد میکند
     //اینها روی صفحه نمایش داده خواهند شد
     // یک نخ ایجاد میکند تا دستورات تایپشده روی صفحهکلید را بخواند
     //اینها بهعنوان پاسخ برای کلاینت ارسال خواهند شد
     // فرآیند زمانی پایان مییابد که دستور «end» از طریق صفحهکلید وارد شود

    final String syntaxe="Syntaxe : pg port";
   // متغیر نمونه
         //آیا آرگومانی وجود دارد
     if(args.length != 1)
        erreur(syntaxe,1);

         // پورت باید یک عدد صحیح بزرگتر از 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);

     // سرویس گوش دادن ایجاد میشود
    ServerSocket ecoute=null;
    int nbClients=0;    // تعداد کلاینتهای پردازششده
        try{
             // سرویس ایجاد میشود
            ecoute=new ServerSocket(port);
             // نظارت
            System.out.println("Serveur générique lancé sur le port " + port);

             //حلقه سرویس مشتری
            Socket client=null;
            while (true){ //حلقه بینهایت  با Ctrl-C خاتمه مییابد
                 // در انتظار مشتری
                client=ecoute.accept();

                 // سرویس توسط نخهای جداگانه اجرا میشود
                nbClients++;

                 // رشتههای خواندن/نوشتن ایجاد میشوند
        new ServeurSend(client,nbClients).start();
        new ServeurReceive(client,nbClients).start();

                // به شنود برای درخواستها بازمیگردد
            }// پایان حلقه while
        }catch(Exception ex){
             //خطا گزارش میشود
            erreur("L'erreur suivante s'est produite : " + ex.getMessage(),3);
        }//catch
    }// پایان برنامه اصلی

     //نمایش خطاها
    public static void erreur(String msg, int exitCode){
         // نمایش خطا
        System.err.println(msg);
         // خاموشی با خطا
        System.exit(exitCode);
    }//خطا
}//کلاس

class ServeurSend extends Thread{
    //کلاس مسئول خواندن ورودی صفحهکلید
     // و ارسال آنها به یک کلاینت از طریق یک کلاینت TCP که به سازنده پاس داده شده است

    Socket client;    // کلاینت TCP
    int numClient;        // شماره مشتری

     // سازنده
    public ServeurSend(Socket client, int numClient){
         // توجه داشته باشید که مشتری TCP
        this.client=client;
         // و شماره آن
        this.numClient=numClient;
    }//سازنده

     // متد Runِ نخ
    public void run(){

        // دادههای محلی
        PrintWriter OUT=null;        //جریان نوشتن شبکه
        String réponse=null;        // ورودی صفحهکلید
    BufferedReader IN=null;    //جریان صفحهکلید

        // ردیابی
        System.out.println("Thread de lecture des réponses du serveur au client "+ numClient + " lancé");
         // پردازش خطا
        try{
             // ایجاد جریان نوشتن شبکه
            OUT=new PrintWriter(client.getOutputStream(),true);
      // ایجاد جریان صفحهکلید
      IN=new BufferedReader(new InputStreamReader(System.in));
            //حلقه ورودی و ارسال فرمان
            while(true){
                 //شناسایی مشتری
                System.out.print("--> " + numClient + " : ");
                 // خواندن پاسخ تایپشده روی صفحهکلید
                réponse=IN.readLine().trim();
                // تمام شد؟
                if (réponse.toLowerCase().equals("fin")) break;
                //ارسال پاسخ به سرور
                OUT.println(réponse);
                 // پاسخ بعدی
            }//در حالی که
        }catch(Exception ex){
             // خطا
            System.err.println("L'erreur suivante s'est produite : " + ex.getMessage());
        }//catch
         //پایان  بستن جریانها
        try{
            OUT.close();client.close();
        }catch(Exception ex){}
         // نشاندهنده پایان نخ
        System.out.println("[fin du Thread de lecture des réponses du serveur au client "+ numClient+ "]");
    }//اجرا
}//کلاس

class ServeurReceive extends Thread{
    //کلاسی که مسئول خواندن خطوط متنی ارسالشده به سرور است 
     // از طریق یک کلاینت TCP که به سازنده پاس داده شده است

    Socket client;    // کلاینت TCP
    int numClient;        // شماره مشتری

     // سازنده
    public ServeurReceive(Socket client, int numClient){
         // توجه به کلاینت TCP
        this.client=client;
         // و شماره آن
        this.numClient=numClient;
    }//سازنده

     // متد Run نخ
    public void run(){

        // دادههای محلی
        BufferedReader IN=null;        //جریان خواندن شبکه
        String réponse=null;        // پاسخ سرور

         //ردیابی
        System.out.println("Thread de lecture des demandes du client "+ numClient + " lancé");
         // مدیریت خطا
        try{
             //ایجاد جریان خواندن شبکه
            IN=new BufferedReader(new InputStreamReader(client.getInputStream()));
            //حلقه برای خواندن خطوط متن از جریان IN
            while(true){
                 // خواندن جریان شبکه
                réponse=IN.readLine();
                 //آیا جریان بسته است؟
                if(réponse==null) break;
                //نمایش
                System.out.println("<-- "+réponse);
            }//در حالی که
        }catch(Exception ex){
            // خطا
            System.err.println("L'erreur suivante s'est produite : " + ex.getMessage());
        }//گرفتن
         //پایان  بستن جریانها
        try{
            IN.close();client.close();
        }catch(Exception ex){}
         // نشاندهنده پایان نخ
        System.out.println("[fin du Thread de lecture des demandes du client "+ numClient+"]");
    }//اجرا
}//کلاس

8.3. JAVASCRIPT

در این بخش، سه مثال از نحوهٔ استفاده از جاوااسکریپت در صفحات WEB را نشان می‌دهیم. ما بر پردازش فرم تمرکز کرده‌ایم، اما جاوااسکریپت می‌تواند کارهای بسیار بیشتری انجام دهد.

8.3.1. بازیابی اطلاعات از یک فرم

مثال زیر نشان می‌دهد چگونه می‌توان در مرورگر داده‌های واردشده توسط کاربر در یک فرم را بازیابی کرد. این کار معمولاً امکان پیش‌پردازش را پیش از ارسال داده‌ها به سرور فراهم می‌کند.

8.3.1.1. فرم

ما یک فرم حاوی رایج‌ترین اجزا و یک دکمه «نمایش» داریم که امکان نمایش ورودی‌های کاربر را فراهم می‌کند.

Image

8.3.1.2. کد

<html>

  <head>
    <title>Un formulaire traité par Javascript</title>
    <script language="javascript">
      function afficher(){
         // داده‌های فرم را در یک لیست نمایش می‌دهد

         //ابتدا لیست را پاک می‌کند
        effacerInfos();

         //نمایش مقادیر فیلدهای #
        with(document.frmExemple){
           // میدان مخفی
          ecrire("champ caché="+cache.value);
           // میدان متن تک‌خطی
          ecrire("champ textuel simple="+simple.value);
           // میدان متنی چندگانه
          ecrire("champ textuel multiple="+lignes.value);
          //دکمه‌های رادیویی
          for(i=0;i<radio.length;i++){
            texte="radio["+i+"]="+radio[i].value;
            if(radio[i].checked) texte+=", coché";
            ecrire(texte);
          }//برای
             // چک‌باکس‌ها
          for(i=0;i<qcm.length;i++){
            texte="qcm["+i+"]="+qcm[i].value;
            if(qcm[i].checked) texte+=", coché";
            ecrire(texte);
          }//برای
           //لیست کشویی
          ecrire("index sélectionné dans le menu="+menu.selectedIndex);
          for(i=0;i<menu.length;i++){
            texte="menu["+i+"]="+menu.options[i].text;
            if(menu.options[i].selected) texte+=",sélectionné";
            ecrire(texte);
          }//برای
           //فهرست چندگزینه‌ای
          for(i=0;i<lstVoitures.length;i++){
            texte="lstVoitures["+i+"]="+lstVoitures.options[i].text;
            if(lstVoitures.options[i].selected) texte+=",sélectionné";
            ecrire(texte);
          }//برای
           //رمز عبور
          ecrire("mot de passe="+passwd.value);
        }//با
      }//تابع

      function ecrire(texte){
         //متن را به فهرست اطلاعات می‌نویسد
        frmInfos.lstInfos.options[frmInfos.lstInfos.length]=new Option(texte);
      }//write

      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. بیان‌های منظم در جاوااسکریپت

از سمت مرورگر، جاوااسکریپت می‌تواند برای بررسی اعتبار داده‌های واردشده توسط کاربر قبل از ارسال آن‌ها به سرور استفاده شود. در اینجا برنامه‌ای برای آزمایش این عبارت‌های منظم ارائه شده است.

8.3.2.1. صفحهٔ آزمون

Image

8.3.2.2. کد صفحه

<html>

  <head>
    <title>Les expressions régulières en Javascript</title>
    <script language="javascript">
      function afficherInfos(){
        with(document.frmRegExp){
           // آیا کاری برای انجام دادن هست؟
          if (! verifier()) return;
          // مشکلی نیست – بیایید نتایج قبلی را پاک کنیم
          effacerInfos();
           //در حال بررسی قالب
          modele=new RegExp(txtModele.value);
          champs=modele.exec(txtChaine.value);
          if(champs==null)
             //تطابقی بین قالب و رشته وجود ندارد
            ecrireInfos("pas de correspondance");
          else{
             //تطابق – نمایش نتایج
            ecrireInfos("Il y a correspondance");
            for(i=0;i<champs.length;i++)
              ecrireInfos("champs["+i+"]=["+champs[i]+"]");
          }//در غیر این صورت
        }//با
      }//تابع

      function ecrireInfos(texte){
        //متن را به فهرست اطلاعات می‌نویسد
        document.frmRegExp.lstInfos.options[document.frmRegExp.lstInfos.length]=new Option(texte);
      }//نوشتن

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

      function jouer(){
         //قالب را با رشته موجود در مثال انتخاب‌شده بررسی می‌کند
        with(document.frmRegExp){
          txtModele.value=lstModeles.options[lstModeles.selectedIndex].text
          txtChaine.value=lstChaines.options[lstChaines.selectedIndex].text
          afficherInfos();
        }//با
      }//اجرا

      function ajouter(){
         //تست فعلی را به مثال‌ها اضافه می‌کند
        with(document.frmRegExp){
          // آیا کاری برای انجام دادن دارد؟
          if (! verifier()) return;
           //اضافه کردن
          lstModeles.options[lstModeles.length]=new Option(txtModele.value);
          lstChaines.options[lstChaines.length]=new Option(txtChaine.value);
           // پاک کردن ورودی‌ها
          txtModele.value="";
          txtChaine.value="";
        }//با
      }//اضافه کنید

      function verifier(){
         //بررسی کنید که فیلدهای ورودی خالی نباشند
        with(document.frmRegExp){
          champs=/^\s*$/.exec(txtModele.value);
          if(champs!=null){
            alert("Vous n'avez pas indiqué de modèle");
            txtModele.focus();
            return false;
          }//اگر
          champs=/^\s*$/.exec(txtChaine.value);
          if(champs!=null){
            alert("Vous n'avez pas indiqué de chaîne de test");
            txtChaine.focus();
            return false;
          }//اگر
           // درست است
          return true;
        }//با
      }//بررسی
    </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

8.3.3.1. فرم

Image

8.3.3.2. کد

<html>

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

    <script language="javascript">
       // افزودن
      function ajouter(L1,L2,T){
         //مقدار فیلد T را به لیست‌های L1 و L2 اضافه می‌کند
           //آیا اقدام خاصی لازم است؟
          champs=/^\s*$/.exec(T.value);
          if(champs!=null){
            // میدان خالی است
            alert("Vous n'avez pas indiqué la valeur à ajouter");
            txtElement.focus();
            return;
          }//اگر
           //عنصر اضافه می‌شود
          L1.options[L1.length]=new Option(T.value);
          L2.options[L2.length]=new Option(T.value);
          T.value="";
      }//اضافه

       //پاک کردن
      function vider(L){
         // لیست L را پاک می‌کند
        L.length=0;
      }//پاک

      //انتقال
      function transfert(L1,L2,simple){
        //آیتم‌های انتخاب‌شده از لیست L1 را به L2 منتقل می‌کند

         // کاری هست؟
         // شاخص آیتم انتخاب‌شده در L1
        index1=L1.selectedIndex;
        if(index1==-1){
          alert("Vous n'avez pas sélectionné d'élément");
          return;
        }//اگر
         // حالت انتخاب برای آیتم‌های لیست چیست
        if(simple){ //انتخاب تکی
          element1=L1.options[index1].text;
           //افزودن در L2
          L2.options[L2.length]=new Option(element1);
          //حذف در L1
          L1.options[index1]=null;
        }//تک
        if(! simple){ //انتخاب چندگانه
           //لیست ۱ را به ترتیب معکوس پیمایش می‌کند
          for(i=L1.length-1;i>=0;i--){
            //عنصر انتخاب‌شده است؟
            if(L1.options[i].selected){
               //آن را به L2 اضافه می‌کند
              L2.options[L2.length]=new Option(L1.options[i].text);
              //آن را از L1 حذف می‌کند
              L1.options[i]=null;
            }//اگر
          }//برای i
        }//اگر ساده!
      }//انتقال
   </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>