Единственное различие между обычным CGI приложением, которое использует BDE для получения данных и нашим приложением без использования BDE это производительность. Кроме того, наше CGI всего лишь 70 KB, оно не нуждается в загрузке BDE, так что время загрузки еще меньше (в результате еще более высокая производительность). В действительности реальные CGI приложения, использующие BDE, часто используют ISAPI (Information Server API) или NSAPI (Netscape Server API) расширения для сохранения CGI приложения "все-время-в-полете (in the air)".
Еще больше можно повысить производительность, если вместо файла записей использовать массив записей с предварительно инициализированными значениями! Вместо создания файла с записями, Я генерирую Паскаль код для этой цели. Таким образом, я могу генерировать исходный Паскаль код сразу с нужной информацией. Не нужды в файле записей. И сразу после компиляции я имею одиночное приложение на Дельфи 2, размером всего 77824 байта, которое содержит информацию об 44 книгах внутри самого себя.
Книги внутри, разбор переменных среды, чтение стандартного ввода, генерация HTML страницы и отправка ее на стандартный вывод с динамическим формированием содержимого в зависимости от запроса на форме. Уверен, что единственный способ получить еще более быстрое приложение, это вернуться обратно к статическим страницам без запросов.
Код для подсчета обращений весьма прост. Для поля на форме, которое было выбрано, мы проходим через все записи и добавляем единичку в соответствующую запись при совпадении информации.
if DataRec.Author <> '' then
begin
{$IFDEF DEBUG}
writeln('Author: ',DataRec.Author,'<BR>');
{$ENDIF}
for i:=1 to Books16 do
if Pos(DataRec.Author,Book16[i].Author) <> 0 then
Inc(Result16[i]);
for i:=1 to Books32 do
if Pos(DataRec.Author,Book32[i].Author) <> 0 then
Inc(Result32[i])
end;
Заметим, что конструкция {$IFDEF DEBUG} может быть использована для вывода значения входного поля в стандартный вывод, так что мы можем использовать наше CGI приложение для отладки формы. Отладка вашего CGI приложения может оказать трудной задачей, поскольку вам нужен Web сервер и браузер для этого…
2.2.10. Результаты запроса
Теперь посмотрим на последнюю часть CGI приложения: часть, в которой генерируется HTML код. Здесь я использую другое свойство расширенного HTML, именованные таблицы, что бы вывод выглядел красивее. Для каждой записи, у которой счетчик более единицы, я выводу счетчик, название, автора, издательство, ISBN, уровень, техническое содержание, качество книги, стоимость и общее значение. Я также включаю ссылку из названия на другое место, где находится более подробное описание. С помощью этого великолепного свойства динамических HTML страниц: вы даже можете включать ссылки на статические страницы, так как результат запроса, часто стартовая точка для прыжка в другое место!
writeln('<HR>');
writeln('<P>');
writeln('<H3>The following books have been found for you:</h3>');
writeln('<TABLE BORDER>');
writeln('<TR>');
writeln('<TH><B>Hits</B></TH>');
writeln('<TH><B>Title</B></TH>');
writeln('<TH><B>Author</B></TH>');
writeln('<TH><B>Publisher</B></TH>');
writeln('<TH><B>ISBN</B></TH>');
writeln('<TH><B>Level</B></TH>');
writeln('<TH>Con</TH>');
writeln('<TH>Wri</TH>');
writeln('<TH>Val</TH>');
writeln('<TH><B>Tot</B></TH>');
writeln('</TR>');
После того как заголовок написан, самое время выводить сами записи. Я не хочу сортировать их по рейтингу от 5 до 1, так что я просто иду по списку книг и печатаю каждую со своим рейтингом. Этот путь, потому что я знаю, что книги уже отсортированы по рейтингу в основной базе delbooks.db (которая отсортирована по уровню и рейтингу). Обычно книги в верху списка уже лучший ответ на заданный вопрос.
if DataRec.Delphi2 then
begin
for Hits := 5 downto 1 do
begin
for i:=1 to Books32 do if Result32[i] = Hits then
begin
writeln('<TR>');
writeln('<TD>',Roman[Hits],'</TD>');
writeln('<TD><A HREF="',root32,Book32[i].HREF,'">',Book32[i].Title,'</A></TD>');
writeln('<TD>',Book32[i].Author,'</TD>');
writeln('<TD>',Book32[i].Publisher,'</TD>');
writeln('<TD>',Book32[i].ISBN,'</TD>');
writeln('<TD>',Level[Book32[i].Level],'</TD>');
writeln('<TD>',Book32[i].TechnicalContentsQuality,'</TD>');
writeln('<TD>',Book32[i].QualityOfWriting,'</TD>');
writeln('<TD>',Book32[i].ValueForMoney,'</TD>');
writeln('<TD><B>',Book32[i].OverallAssessment,'</B></TD>');
writeln('</TR>')
end
end;
if DataRec.Delphi1 then writeln('<TR></TR>')
end;
if DataRec.Delphi1 then
begin
for Hits := 5 downto 1 do
begin
for i:=1 to Books16 do if Result16[i] = Hits then
begin
writeln('<TR>');
writeln('<TD>',Roman[Hits],'</TD>');
writeln('<TD><A HREF="',root16,Book16[i].HREF,'">',Book16[i].Title,'</A></TD>');
writeln('<TD>',Book16[i].Author,'</TD>');
writeln('<TD>',Book16[i].Publisher,'</TD>');
writeln('<TD>',Book16[i].ISBN,'</TD>');
writeln('<TD>',Level[Book16[i].Level],'</TD>');
writeln('<TD>',Book16[i].TechnicalContentsQuality,'</TD>');
writeln('<TD>',Book16[i].QualityOfWriting,'</TD>');
writeln('<TD>',Book16[i].ValueForMoney,'</TD>');
writeln('<TD><B>',Book16[i].OverallAssessment,'</B></TD>');
writeln('</TR>')
end
end
end;
writeln('</TABLE>');
writeln('<HR>');
writeln('<A HREF="http://www.drbob42.com">Dr.Bob''s Delphi Clinic</A>');
writeln('</BODY>');
writeln('</HTML>');
writeln;
Free
end
Страницу HTML с результатом, сгенерированную по запросу мы модем увидеть выполнив CGI приложение. Для этого требуется (персональный) Web сервер. По этому я написал небольшую программу отладки, используя Delphi 2.01 и NetManage HTML control:
Я надеюсь, что я показал, как мы можем писать интерактивные Интернет (Интранет) CGI приложения с помощью Delphi 2 используя CGI, WinCGI и Delphi 3 ISAPI/NSAPI Web Modules. Лично я планирую делать многое с помощью Дельфи для Интернет и Интранет.
Многое из того, что вы узнали, позволяет вам писать Интернет приложения с помощью Delphi. Особенно с помощью новых средств в Delphi 3 таких как ActiveForms и Web Modules. Но иногда мы хотим сделать, что еще быстрее и проще. Иногда мы просто хотим загрузить файл из Интернета. В терминах Интернета это означает, что мы хотим использовать FTP (file transfer protocol) клиента. И если вы верите мне, то вам не требуется ни какой FTP клиент, но если вы верите мне, то вы можете написать свой…
Как я сказал во введении, FTP означает File Transfer Protocol, который описан в RFC 959. Модель связи FTP может быть реализована с помощью сокетов, но это более низкоуровневое решение и если вы посмотрите спецификацию, то поймети, что написание программы FTP клиента с нуля не такая уж простая задача. С другой стороны, мы можем использовать NetManage TFTP компонент из Delphi 2.01 (и выше) и C++Builder. Я пробовал использовать этот компонент несколько раз, и нашел его просто глюкавым, особенно для файлов свыше 10 Kb. Я могу понять, почему Microsoft (первый разработчик Internet Solutions Pack) не захотела использовать его и продала затем NetManage, которая тоже не справилась с ним и продала далее фирме NetMasters. Проблема в том, что Internet Solutions Pack – хотя и бесплатный – основан на наборе с ограничениями ActiveX, и каждая компания которая использует его также имеет более лучшее решение (обычно не бесплатно). Поддержка и документация всегда отвратительная…
Так что же, назад к низкоуровневому программированию? Ни в коем случае. Как всегда на помощь приходит Microsoft