Rambler's Top100 Service калинин.ru / программирование / c и c++ /  << 20.09.00 >>

Библиотека консорциума W3, libwww

Популярный нынче термин "веб-программирование" обычно подразумевает под собой программирование, в лучшем случае, на perl, в худшем --- на PHP, в совсем тяжелом --- на JavaScript. Ничуть не пытаюсь обидеть людей, которые этим занимаются, просто смешно выделять "программирование на Perl" в отдельную нишу, прежде всего потому что специфика его использования отнюдь не в "веб-программировании".

Кроме того, мне вообще тяжело понять, чем принципиально отличается создание CGI-программ от "просто программ", кроме использования специализированного интерфейса для получения данных.

Тем не менее, "веб-программирование" действительно существует. Заключается оно не в генерации на лету HTML-страничек по шаблонам на основании информации из базы данных, потому что это относится именно к использованию БД. "Веб-программирование" это работа с сетевыми протоколами передачи данных, да и сетями вообще. Более точно, это "программирование для сетей, основанных на TCP/IP". А подобное программирование подразумевает прежде всего передачу данных, а не их обработку --- скажите мне, что и куда передает CGI-программа по сети? Данные передает веб-сервер, а CGI используется как метод расширения возможностей сервера.

Настоящее веб-программирование это программирование веб-серверов и веб-клиентов. Т.е., написать Apache, Internet Explorer или lynx --- это веб-программирование.

Некоторые могут сказать, что я тут слишком строго подошел к программированию CGI-приложений и, если копать дальше, то веб-программирование в том смысле, в котором я его определил только что, является всего-навсего обработкой устройств ввода-вывода (к коим относится в одинаковой степени и сетевая карта, и клавиатура). Ну... да, это будет законный упрек. Только я не собираюсь так далеко заходить, мне просто хочется точнее определить термин "веб-программирование". Все дело в том, что генерация страниц "на лету" подразумевает то, что они будут отдаваться по сети, но это совершенно не обязательно. Неужели что-то принципиальным образом изменится в CGI-приложении, если его результаты будут сохраняться на жесткий диск? А внутри того, что подсовывется на вход PHP-интерпретатору? Ничего не изменится. Вообще. Для них главным является корректная установка нужных переменных среды окружения, а тот факт, подключен компьютер к сети, или нет, их не волнует.

Проблему передачи или получения данных через TCP, конечно же, тоже можно аналогичным образом развернуть и сказать, что с появлением интерфейса сокетов (BSD sockets) передача данных на расстояние ничем принципиально не отличается от работы с файлами на локальном диске.

В принципе это так. Потому что, если откинуть использование функций, связанных с инициализацией сокетов, в остальном с ними можно общаться как с традиционными файловыми дескрипторами.

Все это хорошо, но до некоторой поры. Все дело в том, что два компьютера могут находится рядом и быть соединены всего-лишь одним кабелем, а могут отстоять друг от друга на тысячи километров. И хотя скорость передачи данных в пределах одного кабеля очень большая, то при использовании различных устройств для соединения кабелей друг с другом, происходит замедление передачи данных и чем "умнее" будет устройство, тем медленее через него будут передаваться данные.

Это первое отличие. При работе с файловой системой программист никогда не думает о том, с какой скоростью у него считается файл или запишется (точнее, думает, но реже ;) ), буферизацая обычно уже реализована на уровне операционной системы или библиотеки языка программирования, а при работе с сетью задержки могут быть очень велики и в это время программа будет ожидать прихода новых данных, вместо того, что бы сделать что-либо полезное. Таким образом приходит необходимость разбивать программу на совокупность потоков и программирование превращается в ад, потому что ничего хорошего это не принесет, только лишние проблемы. Связано это с тем, что разделение программы на несколько одновременно выполняющихся потоков требует очень большой внимательности и поэтому чревато серьезными обшибками. А перевод существующей однопоточной программы в многопоточную, вообще занятие неблагодарное.

Второе отличие, в принципе, вытекает из первого, но стоит несколько отдельно, потому что это требование более жесткое. Все дело в том, что передача данных обычно не ограничивается одним файлом или одним соединением. Обычно сервер обслуживает одновременно несколько клиентов или клиент одновременно пытается получить доступ одновременно к нескольким ресурсам (они так выкачиваются быстрее, чем по-одиночке). Тем самым приходиться открывать одновременно несколько сокетов и пытаться одновременно обработать их все.

Для подобной работы, в принципе, не требуется реальная многопоточность, существует такой вызов (или подобный ему в других операционных системах), называемый select(), который переводит программу в режим ожидания до тех пор, пока один (или несколько) файловых дескрипторов не станет доступным для чтения или записи. Это позволяет без введения нескольких потоков обрабатывать данные из нескольких соединений по мере их прихода.

Третье отличие, по сути, относится к серверным приложениям и выражается в повышенных требованиях к производительности. Все дело в том, что когда один и тот же интернет-ресурс запрашивается большим количеством пользователей одновременно, то становится очень важна скорость реакции на него. В принципе, тут, если использовать CGI-приложения, на них тоже будет распространяться это требование, но в таких ситуациях обычно вставляют нужные обработчики непосредственно в сервер для повышения производительности.

В качестве примера могу привести такой, относительно мало известный web-сервер как thttpd, который сам по себе достаточно прост и не имеет такого количества возможностей как apache, но на сегодняшний день является одним из самых быстрых веб-серверов.

А теперь, собственно, возвращаясь к теме заметки. Для облегчения написания веб-приложений (именно веб-приложений!) на языках C и C++ была написана библиотека libwww. Она реализует псевдопотоковую событийную модель программы.

Под псевдопотоками понимаетя как раз использование select() для обработки большого количества запросов, а не введение для каждого из них настоящего потока операционной системы. Событийная модель предполагает то, что приложение запускает цикл обработки событий, поступающих от libwww, и в дальнейшем работа программы основывается на выполнении предоставленных обработчиков событий из цикла.

Приложение в этом случае управляется поступающими или инициированными запросами. Кроме этого псевдопараллельного "фетчера" (от слова fetch), в libwww присутствует большое количество готовых обработчиков, которые помогают решать типовые задачи, появляющиеся вместе с "веб-программированием". Например, существует набор "переводчиков", которые позволяют, например, из потока "text/html" сделать поток "text/present" (это в терминологии libwww, "present" означает вид, который будет представлен пользователю). Для этого используется собственный html-парсер (основанный на sgml-парсере с html dtd).

Таким образом, типичное веб-приложение, написанное при помощи libwww, выглядит как набор подпрограмм, обрабатывающие различные сообщения. Это позволяет написать как клиентские, так и серверные программы.

В качестве примера использования libwww, можно вспомнить текстовый браузер lynx, который написан при помощи этой библиотеки.

Впрочем, не буду распространяться долго об архитектуре libwww, желающие могут посмотреть документацию. Теперь мне хотелось бы пройтись по недостаткам.

libwww со временем становится все сложнее и сложнее по причине увеличивающегося набора стандартных обработчиков. Зачастую, достаточно простая задача, но которая не предусмотрена изначально как типовая, может потребовать нескольких часов изучения документации в поисках того, какие обработчики и где должны для этого присутствовать. Не спорю, доскональное знание libwww, вполне вероятно, решит эти проблемы, но откуда же эти знания взять? ;)

Документация на библиотеку не отличается подробностью и, как следствие, понятностью; она сводится к двум-трем строкам комментариев к программным вызовам, при этом местами документация просто устарела. Мой вам совет: если вы используете libwww, то обязательно смотрите исходный текст, по нему станет многое понятно. В качестве примера, могу привести такую веселую вещь. Для того, что бы отследить контекст разбора HTML, вводится специальный объект типа HText, который используется в обработчиках событий от парсера в качестве "внешней памяти". Это как указатель this в C++, т.е. реализация объектов на языке C. Тип HText целиком предоставляется пользователем, вместе с callback-функциями создания и удаления. Прежде чем его использовать, надо зарегистрировать эти функции (причем обязательно парой, т.е. надо обязательно указать и функцию создания объекта, и функцию разрушения), которые, если следовать документации, будут вызваны, соответственно, для создания и удаления объекта при начале и конце разбора соответственно.

Это все пока что "хорошо". "Плохо" --- функция разрушения не вызывается никогда. В частности, в документации этого нет, но видно по исходному тексту, где в том месте, где должен был находится вызов удаляющей функции, находится комментарий, в котором написано что забота об удалени ложится на плечи приложения, а не библиотеки libwww. Кто при этом мешает вызвать переданную функцию, я не понял. Кстати сказать, примеры использования объекта HText в поставляемых с libwww приложениях из каталога Examples, рассчитаны на то, что функция удаления будет вызвана.

И это не единственное забавное место в библиотеке. Все это решаемо, конечно, но лучше если вы будете сразу же смотреть исходный текст libwww, по нему значительно больше можно понять, чем по предоставленной документации.

Резюме

Использование libwww позволяет быстро написать типичное web-приложение, например, "робота", который выкачивает определенные документы и каким-то образом их анализирует. Тем не менее, использовать libwww в своих программах не всегда просто из-за проблем с документацией на нее.


Версия для печати


  Ссылки по теме:
http://www.w3c.org/Library
   Официальная страница libwww.
  Рядом в разделе:
Шаманство, или ошибки работы с памятью (25.09.00)
   Когда программа становится внушительной по своему содержанию (то есть, не по количеству строчек, а по непонятности внутренних связей), то ее поведение...   >>>>
Инварианты внутри программы (18.09.00)
   Вы когда-нибудь задумывались, над тем, как вы пишите программы? Если нет, то, я думаю, сегодняшняя заметка будет вам полезна. Итак, как...   >>>>
  Рядом по дате:
Автоматизация заполнения базы данных "по студентам", немного статистики (21.09.00)
   Я уже провел две лабораторных работы и один семинар с первым курсом в этом семестре и, так как на лабораторных мне...   >>>>
Памятка завхозу (19.09.00)
   Шла уже третья неделя. Мы выходили из района. Восемьдесят километров тайги, по уши снега среди бурелома и на кончике азимута маленький...   >>>>
  Содержание:
Заглавная страница
Мой блог
Мое резюме
Дайджест
Программирование
   C&C++
Сети
Unix
Алгоритмы
Оптимизация
Соревнования
Отвлеченно
XML
TeX
Просто так
Студенческое
Туризм
  Байки
Фотографии
Комментарии
   Книги
Web-ресурсы
Фильмы
Интернет
Программное обеспечение
Жизнь
Благодарности
Форум
Хронология
 
  В этом разделе:
Простой, но полезный аллокатор памяти (18.02.03)
   Эта заметка --- продолжение "Postfix изнутри" в том смысле, что в качестве примера опять берется postfix. Но если в прошлый раз...   >>>>
C или C++? (09.07.01)
   Существуют два диаметрально противоположенных, но одинаково распространенных мнения, которые можно выразить как "C++ это C с классами" и "C++ и C...   >>>>
Религия и goto (14.04.01)
   Начнем несколько издалека. В программировании существует тенденция к алгоритмизации самого процесса программирования. То есть, выведение некоторых универсальных правил, использование которых в...   >>>>
ploticus (16.10.00)
   Есть такая программа, предназначенная для создания графиков различных видов из командной строки, называется ploticus. Программа сама по себе достаточно удобная ---...   >>>>
Шаманство, или ошибки работы с памятью (25.09.00)
   Когда программа становится внушительной по своему содержанию (то есть, не по количеству строчек, а по непонятности внутренних связей), то ее поведение...   >>>>
Библиотека консорциума W3, libwww (20.09.00)
   Популярный нынче термин "веб-программирование" обычно подразумевает под собой программирование, в лучшем случае, на perl, в худшем --- на PHP, в совсем...   >>>>
Инварианты внутри программы (18.09.00)
   Вы когда-нибудь задумывались, над тем, как вы пишите программы? Если нет, то, я думаю, сегодняшняя заметка будет вам полезна. Итак, как...   >>>>
Содержание раздела полностью...
   Примерно в тоже время
Автоматизация заполнения базы данных "по студентам", немного статистики (21.09.00)
   Я уже провел две лабораторных работы и один семинар с первым курсом в этом семестре и, так как на лабораторных мне...   >>>>
Памятка завхозу (19.09.00)
   Шла уже третья неделя. Мы выходили из района. Восемьдесят километров тайги, по уши снега среди бурелома и на кончике азимута маленький...   >>>>
Хронология полностью...
   Содержание
Заглавная страница
Мой блог
Мое резюме
Дайджест
Программирование
  C&C++
Сети
Unix
Алгоритмы
Оптимизация
Соревнования
Отвлеченно
XML
TeX
Туризм
  Байки
Фотографии
Комментарии
  Книги
Web-ресурсы
Фильмы
Интернет
Программное обеспечение
Жизнь
Студенческое
Просто так
Благодарности
Форум
Хронология
© 2000-2008, Andrey L. Kalinin
mailto:andrey@kalinin.ru
Rambler's Top100