div.main {margin-left: 20pt; margin-right: 20pt}
Mobile Dictionaty 
Я смекнул , что у меня есть хороший мозг, что работает он 
великолепно и что следует этим
воспользоваться.
  Владимир Набоков, 
"Лолита"
В этой небольшой статье вы найдете пример написания простого 
приложения клиент-сервер, клиентом служит CGI-скрипт на Perl, клиентом является 
графическое (AWT) Java приложение. Статья содержит информацию по следующим 
вопросам: 
  Основы CGI программирования. 
  Написание графического интерфейса (AWT). 
  Описание модели делегирования событий (AWT Events). 
  Работа Java приложения через HTTP прокси-сервер. 
  Сохранение и загрузка пользовательских свойств. 
  Чтение потока данных, содержащего кириллические символы. 1. 
Структура приложения. 
 Приложение работает как on-line 
словарь (англо-русский и русско-английский), оно состоит из клиентской и 
серверной частей. Сервер - любой HTTP сервер, умеющий запускать CGI скрипты 
(Apache, IIS, etc). Скрипт, работающий на сервере, написан на Perl. Во-первых, 
это улучшает переносимость на другую платформу, во-вторых, этот язык широко 
испрользуется для серверных CGI приложений, и в-третьих, Perl - язык для 
обработки текстовых данных (чем он и занимается по сути в нашем случае). Скрипт 
универсален, он может работать как с обычным HTTP браузером (MSIE, NC), так и с 
клиентом, не поддерживающим HTML (в нашем случае - это Java Application). Клиент 
- (как уже упоминалось выше) - графическое Java приложение, умеющее работать 
через HTTP прокси. 
  2. Серверная часть. 
 Как уже упоминалось выше, серверная часть состоит из CGI скрипта и 
нескольких файлов словарей в plain-text формате. Работа скрипта заключается в 
следующем: 
  Прием HTTP запроса (http request) от клиента. 
  Поиск перевода слова заданного в заголовке HTTP запроса по всем словарям. 
  Выдача HTTP ответа (http response) в формате, запрошенном клиентом. 
 Рассмотрим кратко как вышесказанное выполняется в 
коде:
  Используется стандартный модуль CGI.pm (хотя никто не мешает 
получать параметры, разбирая переменную $ENV{'QUERY_STRING'}; ). 
Этот модуль являктся de-facto стандартом для web-программистов, позволяет 
сократить время разработки приложения и улучшить его защищенность. Мы создаем 
объект req (один на все CGI приложение), посредством которого можем 
обрабатывать запрос и формировать ответ.  #!/usr/bin/perl -w 
###################################################################
# dict.cgi
# author:    Nikolay Zaikin (nikolay_zaikin@mail.ru)
# version:   0.0.2
# created:   24.04.2001
# modified:  24.04.2001
###################################################################
use CGI;
require 'dict.conf';
$req = new CGI;                      
Далее, мы получаем от клиента несколько параметров: 
  word - слово для перевода; 
  type - тип поиска (см. далее), задает алгоритм работы скрипта; 
  app - тип клиента (HTML браузер или java application). В случае, 
если какой-либо параметр не указан, ему присваивается значение по умолчанию (для 
правильной работы скрипта). my $word = $req->param('word');    # word for translating
my $type = $req->param('type');
my $app  = $req->param('app');     # client application (web or java)
$word = ($word) ? $word : "sad";
$type = ($type) ? $type : "1";
$app  = ($app)  ? $app  : "web"; # by default we use web client
 Далее идет "самая главная" строка почти каждого CGI-скрипта, а 
именно, указание клиенту "тип" отправляемого содержимого (Content-type). В 
ручном исполнении это выглядит так: print "Content-type: text/htmlnn";
В нашем, "продвинутом" исполнении это выглядит как: print $req->header;
 В зависимости от типа клиента, начинаем выводить ответ (хочу только 
напомнить, что для сравнения числовых скаляров используется '==', а 
для сравнения строковых скаляров используется 'eq'). И заодно 
засекаем время старта работы скрипта. if ($app eq "web") { 
print <<EOD;
<HTML>
<HEAD>
</HEAD>
<BODY>
        <FONT FACE="Helvetica, Verdana, Arial" SIZE="4">
EOD
$br = "<BR>";
$b1 = "<B>";
$b2 = "</B>";
}
my $start_time = time;
 Открываем директорию со словарями (путь к директории хранится в 
файле dict.conf) как обычный файл, читаем все имена файлов 
(словарей) в массив dicts, отбрасывая имена каталогов в этой 
директории, а также имена двух "специальных" каталогов, которые называются "." 
(указывает на текущий каталог) и ".." (указывает на родительский каталог). 
# open directory with dictionaries
opendir (DIR, $dict_dir) or die "can not open directory: $dict_dir : $!";
# read the directory, excluding folders and files with starting dots
@dicts = grep {!/^./ && -f "$dict_dir/$_"} readdir (DIR);
# close directory with dictionaries
closedir DIR;
 Ниже приведен непосредственно сам поиск перевода слова пр словарям. 
Подробно описывать не буду, думаю, тут все очевидно. Хочу только привести 
несколько комментариев: a. Словари достались мне в виде plain-text файлов, со 
следующей структурой: <n>
<слово 1><n>
<перевод 1><n>
<перевод 1><n>
<n>
<слово 2><n>
<перевод 2><n>
<перевод 2><n>
..........
<n>
<слово N><n>
<перевод N><n>
<перевод N><n>
b. Я выбрал следующие алгоритмы поиска: 
  type=1 Слово начинается с шаблона (для sad будут найдены 
  sad, sadness и т.д.); 
  type=2 Слово строго совпадает с шаблоном (для sad будет найдено 
  только sad); 
  type=3 Слово содержит в своем составе шаблон (для sad будут найдены 
  sad, ambassador, disadvantages и т.д.). my $i=0;
my $ooops=0;
my $oooops=0;
my $new_entry=1;
foreach $dict (@dicts) {
    open (DICT, "$dict_dir/$dict") or die "can not open file: $dict_dir/$dict :$!";
    while (<DICT>) {
        if ($_ eq "n") {$ooops=0;$new_entry=1;} else {$new_entry=0;}
        if ($ooops) {print "$_$br";}
        if (($type eq "1") && (index($_, $word)==0) && ($oooops)) {
            print "n$br". ++$i." : $b1$_$b2$br";
            $ooops=1;
        } elsif (($type eq "2") && ($_ eq "$wordn") && ($oooops)) {
            print "n$br". ++$i." : $b1$_$b2$br";
            $ooops=1;
        } elsif (($type eq "3") && (index($_, $word)>=0) && ($oooops)) {
            print "n$br". ++$i." : $b1$_$b2$br";
            $ooops=1;
        } 
                
        $oooops=$new_entry;
    }    
}
 Ну, и окончательно выводим время, затраченное скриптом на поиск 
переводов, и (при необходимости) закрываем HTML тэги. my $finish_time = time;
my $searching_time = $finish_time - $start_time;
if ($app eq "web") { print "<BR><FONT SIZE="2"><I>"; }
print "nsearching time = $searching_time sec";
if ($app eq "web") { print "</I></FONT><BR>n"; 
print <<EOD;
    </FONT>
</BODY>
</HTML>
EOD
}
 На этом описание серверной части закончено. Теперь следует перейти 
к основной теме этой статьи - описанию работы клиентской части приложения (Java 
Applcation). 
  
Май 2001.  Nikolay 
Zaikin 
 
 |