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
|