Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Packages
 Make 
 Iptables 
 Nmap 
 Apache 
 LFS 
 TUX 
 cURL 
 libpcap 
 Parted 
 Httpd 
 File managers 
 FFMPEG 
 RTMP 
 SQL 
 Test 
 Git 
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Linux Kernel 2.6...5170 
 Trees...938 
 Максвелл 3...870 
 Go Web ...821 
 William Gropp...802 
 Ethreal 3...787 
 Gary V.Vaughan-> Libtool...772 
 Ethreal 4...770 
 Rodriguez 6...763 
 Ext4 FS...754 
 Steve Pate 1...754 
 Clickhouse...753 
 Ethreal 1...741 
 Secure Programming for Li...731 
 C++ Patterns 3...716 
 Ulrich Drepper...696 
 Assembler...694 
 DevFS...660 
 Стивенс 9...649 
 MySQL & PosgreSQL...630 
 
  01.01.2024 : 3621733 посещений 

iakovlev.org

Httpd

Основная функция веб-сервера - получить запрос и отослать ответ.

Есть несколько типов серверов - рассмотрим 3 основных :

1. Делают форк на каждый запрос.Примеры - CERN , NCSA 1.3 Это дорогостоящая операция , такие сервера не справляются с большим числом коннектов Есть подразновидность таких серверов , которые используют т.н. нестандатрные процессы - lightweight processes или threads . Примеры - MDMA , phttpd.

2. Т.н. pre-forking - создается повторно используемый пул процессов. Примеры - NCSA 1.4, Apache, Netscape. Высоко-эффективный подход , который отличается сложностью реализации большого количества процессов. Принцип работы апача основан на том , что каждый запрос рассматривается внутри отдельного процесса В апач-конфиге httpd.conf есть параметр - MaxClients - задающий максимальное число таких процессов. Другой параметр - StartServers - задает число таких процессов при старте апача. Эти процессы создаются предварительно сразу. KeepAlive - механизм поддержки коннекта от клиента. Коннект закрывается спустя KeepAliveTimeOut секунд после его открытия. Главное свойство апачевской комбинации - fork + KeepAlive - надежность , т.к. каждый запрос обрабатывается внутри отдельного процесса. При большом трафике увеличивается загрузка cpu , возрастают затраты памяти , и возрастает вероятность достижения критического MaxClients.

3. Один процесс Используется системный вызов select(). Преимущества : высокая скорость , экономное использование памяти , портабельность. Thttpd , mathopd , awhttpd относятся к их числу.

Thttpd
При работе использует минимум ресурсов, необходимых для поддержки HTTP/1.1.
Особенности :
1. Использует не-блокирующее I/O и вызов select() для управления запросами внутри одного-единственного процесса.
2. Поддерживает Basic Authentication для защищенных страниц.
3. Максимальное число пользователей - 1000 и более В юниксе есть системное ограничение на уровне ядра - не более определенного числа одновременных коннектов, обычно это 5 коннектов. В thttpd эта проблема решается с помощью создания своей собственной очереди, в которой может быть произвольное число одновременных коннектов. В качестве лога используется системный вызов syslog.
Некоторые опции-параметры thttpd (config.h) :
1. IDLE_READ_TIMELIMIT - число секунд на чтение запроса из нового коннекта , обычно 300.
2. AUTH_FILE - файл аутентификации для каталога
3. DEFAULT_PORT - порт по умолчанию - 80.
Порядок сборки и установки - достаточно выполнить 3 команды :
make
make install
thttpd -d /usr/local/www -l /var/log/messages_thttpd -T 1251
После инсталяции корневой директорией для thttpd становится каталог /usr/local/www Сам thttpd устанавливается в каталог /usr local/sbin Логирование ведется в 2-х файлах : /var/log/messages и /var/log/messages_thttpd В данном проекте - функциональный подход , все функции статические

Mathopd Все запросы обслуживаются внутри одного процесса и работают на основе 2-х системных вызовов - select() и sendfile(). Сервер в бОльшей степени подходит для раздачи статических файлов, и в идеале он идет в комбинации с апачем , который обслуживает скрипты, при этом апачевский keepalive может быть задисэйблен , что повышает производительность самого апача.
Конфиг mathopd имеет параметр : NumConnections - максимальное число одновременных коннектов - напр. 64 , он может быть увеличен без особого риска. Пока не достигнут этот максимум , mathopd хранит все коннекты - его собственный механизм keepalive, и тут , в отличие от апача , нет блокировки коннекта. Basic Authentication отсутствует. Максимальное число пользователей - 500 и более
Порядок сборки и установки :
make
make install
/usr/local/sbin/mathopd -f mathopd.cfg
После инсталяции корневой директорией для mathopd становится каталог /usr/local/www/data

Последние годы порадовали расцветом интересных реализаций Web-серверов, например, lighttpd, litespeed и mongrel. Достоинствами этих Web-серверов являются различные сочетания производительности, удобства администрирования, портативности, безопасности и других преимуществ. Представленный ниже технический анализ сегмента лёгких Web-серверов призван помочь вам найти среди них наиболее соответствующий требованиям вашего следующего проекта.

Применение в проектах "лёгких" Web-серверов, таких как lighttpd, litespeed и mongrel, дает впечатляющие преимущества. В этой статье мы представляем обзор возможностей и показываем, как их можно применять.

Что должен делать Web-сервер?

Основное действие конечного пользователя в интернете – это "переход на Web-страницу". На самом общем уровне это предполагает совместную работу пары приложений:

  • Web-браузера, такого как Firefox или Internet Explorer, который показывает в удобной для человеческого восприятия форме запрашиваемую страницу, которую он получает от…
  • Web-сервера, находящегося, как правило, на удалённой машине, который отвечает на запрос страницы потоком данных в формате HTML или аналогичном.

С браузерами имеют дело Web-пользователи, которые подходят к их выбору и анализу с надлежащей тщательностью. Напротив, серверы видны только техническому персоналу сайтов. Более того, хотя существует множество различных Web-серверов, около 90% всех сайтов, согласно недавним исследованиям Netcraft, работают всего на двух из них - Apache и Internet Information Server (IIS). Оба эти сервера – тщательно проработанные продукты, обладающие не только очень длинным списком встроенных возможностей, но и процветающим "вторичным рынком" книг, дополнений, консультаций, провайдеров и т.д. Надо ли вновь изобретать обычное колесо?

Да. Web-сервер оценивается по целому ряду важнейших параметров:

  • Эффективность: как быстро он отвечает на запрос?
  • Масштабируемость: продолжает ли сервер работать надёжно, когда к нему одновременно обращаются много пользователей?
  • Безопасность: совершает ли сервер только те операции, которые должен? Какие возможности он предлагает для аутентификации пользователей и шифрования потока обмена информацией? Делает ли его использование более уязвимыми соседние приложения или хосты?
  • Работоспособность: какие у сервера режимы отказа и аварийные ситуации?
  • Соответствие стандартам: поддерживает ли сервер соответствующие RFC?
  • Гибкость: можно ли настроить сервер для принятия большого количества запросов или динамических страниц, требующих значительных вычислений, или сложной аутентификации, или ...?
  • Требования к платформе: на каких платформах возможно использование сервера? Предъявляет ли он особые требования к аппаратной платформе?
  • Управляемость: легко ли установить и обслуживать сервер? Совместим ли он с организационными стандартами по ведению журналов, аудиту, оценке затрат и т.д.?

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

Самое интересное в лёгких Web-серверах, то, почему они заслуживают такого обзора, как этот – это их далеко не теоретическая конкурентоспособность. Внимательное исследование показывает, что они могут предложить очень многое и за счёт этого успешно конкурировать с Apache и IIS даже во многих обычных ситуациях. Хотя разумно было бы предположить, что лидеры рынка тщательно оптимизированы, чтобы быть непобедимыми (например) в производительности, многие мелкие конкуренты работают быстрее при простом отображении статических Web-страниц. Если вы проделаете свои собственные тесты с этими Web-серверами, у вас возникнет чувство, что вы случайно оказались на гоночном треке на карте и каким-то непостижимым образом обгоняете «порше» и «вайперы». ?? это еще не всё: временами лёгкие Web-серверы дополняют своих больших братьев, а не только соревнуются с ними. Даже если вы знаете, что будете использовать Apache, иногда удается получить от него гораздо больше, объединив его с лёгким партнёром. Часто наилучшее решение состоит в кооперации между двумя или более Web-серверами.

Лёгкость Web-сервера

"Лёгкость", на которой фокусируется этот обзор – это скорее субъективная характеристика, как "искусство" или "аромат". Обычно "лёгкий" подразумевает простой, легко инсталлируемый, хорошо налаженный, нетребовательный и устойчивый – меньшего размера и менее сложный, чем Apache и IIS, которые в попытке удовлетворить свой большой рынок превратились в довольно громоздкие конструкции. ??з-за сложности и размера мы исключаем из рассмотрения Java Web Server, AOLserver и Zeus, несмотря на их интригующую переносимость и производительность.

Достаточно лёгкие серверы открывают возможности, недоступные лидерам рынка и другим "тяжёлым" альтернативам. К примеру, весь сервер может поместиться в одном файле. Это удобно для разработчика, так как позволяет носить с собой все инструменты, которые нужны ему для продуктивной работы; даже если вы используете на вашем производственном сервере Apache, вы можете сидеть в гостиничном номере и экспериментировать с новыми идеями, запуская их на лёгком сервере, инсталляция которого занимает секунды. Также из-за своей нетребовательности лёгкие серверы успешно функционируют на машинах, которые просто не могут выдержать тяжесть IIS.

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

Почти все лёгкие Web-серверы имеют в той или иной степени открытый исходный код. Если нам требуется особое поведение Web-сервера, то описанные ниже серверы настолько малы, что их легко понять и, следовательно, усовершенствовать (есть лишь пара исключений). Эти Web-серверы – отличный исходный материал для проектов, в которых Web-серверы встраиваются в специальное ли оборудование или в специфические приложения, предназначенные для работы на компьютерах общего назначения. Они также широко используются на обычных Web-сайтах:

  • YouTube использует lighttpd для быстрой доставки архивированного контента, например, видео;
  • cdServe работает на CD-дисках "German Woodworking Machinery and Tools";
  • LiteSpeed «отметился» в twitter, www.funnyoride.com, www.airliners.com, WordPress.com, fanfiction.com, SlashGear, www.forumactif.com и в других заметных Web-сайтах;
  • OpenSUSE, RubyOnRails, MarkaBoo и несколько других заметных сайтов опираются на Mongrel;
  • thttpd работает на ht.com, mtv.com, The Drudge Report, garfield.com и др.
  • и т.д.

Вот пример удобства лёгких серверов для разработчиков: в нашей компании мы имеем дело со специальным оборудованием для офисной телефонии. С ним используется специализированное программное обеспечение, которое работает как обычное Linux®-приложение. С помощью всего одного дополнительного файла и небольшой настройки init.d легко добавить высокоэффективную "Web-консоль", которая обеспечивает управляющий интерфейс для аппаратного и программного обеспечения. Конечные пользователи получают возможность отслеживать и конфигурировать свою аппаратуру из любого браузера без установки специального оборудования и других сложностей, которые были характерны для "вертикального" оборудования.

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

Лёгкие серверы играют свою роль даже в реальных вычислительных центрах, включая перечисленные выше солидные сайты и не только их. Особо высокопроизводительные сайты сегментируют свои операции, чтобы извлечь максимальную выгоду из кэширования, прокси-серверов и т.д. Сайт на основе Apache, к примеру, может иметь архитектуру, в которой медленно изменяющиеся изображения доставляются посредством «минималистского» Web-сервера из выделенной файловой системы. То, что видит в действительности конечный пользователь – это результат командной работы Apache и одного или нескольких дополнительных Web-серверов, каждый из которых играет роль, в которой он превосходит остальных. Такая конструкция может дать очень быстрые результаты с минимальными затратами на вычисления.

Цели и средства

Хотя лёгкие Web-серверы имеют много общего, внутри данной категории есть и различия. Большинство серверов написаны на C, но среди серверов, которые я тестировал, есть и ряд успешных реализаций на других языках, в том числе на Erlang, Java, Lisp, Lua, Perl, Python и Tcl. Если вы предпочитаете какой-либо язык, вы, возможно, найдёте Web-сервер, написанный на нем.

Для того чтобы выбрать "редкий" язык, может быть множество специфических причин:

  • Образование: работа с лёгким Web-сервером – это серьёзная, но не запредельная задача. Это хороший способ получить опыт работы с языком.
  • Кооперация: в то время как лёгкий Web-сервер, написанный на С, обычно укладывается в 10-50 килобайт, а исполняемые файлы более высокоуровневых языков занимают от 100 килобайт до нескольких мегабайт, исходный код для полного Web-сервера на языке высокого уровня может занимать всего несколько тысяч байт. Такой небольшой код намного легче использовать совместно с коллегами, чем модифицировать Apache.
  • ??сследование: языки высокого уровня делают облегчают эксперименты – например, для добавления новых возможностей HTTP/1.1 может потребоваться всего несколько дополнительных строчек кода. Эти лёгкие серверы – удобный экспериментальный материал.
  • Модификация: добавление HTTP-сервера к существующему приложению, уже написанному на языке высокого уровня, может потребовать увеличения исходного кода всего на несколько строк.

Хорошим примером здесь может служить Athana. Это Web-сервер, написанный на Python. Он поддерживает HTTP multipart (uploading), сессии, cookies и многое другое. Существующий в настоящее время в версии 0.2.1, Athana пока помещается в одном прекрасно организованном исходном файле.

Как уже говорилось, возможности различных лёгких Web-серверов также варьируются, более или менее независимо от использованного языка. Все лёгкие Web-серверы меньше и конфигурируются легче, чем Apache. Некоторые из них быстрее, чем Apache, некоторые намного быстрее; в других упор сделан на безопасность, бесперебойную работу при больших загрузках, расширяемость или экономию памяти. В любом случае в них скорее всего можно полностью разобраться, что уже нереально для Apache.

Какие конкретные продукты стоят за этими возможностями? Даже ограничившись "лёгкими" серверами, мы получаем необозримо огромный выбор. Рассмотрим эти серверы по подкатегориям: ультралёгкие, особо защищенные, использующие особый язык и так далее.

Среди этих категорий я особенно люблю ультралёгкие Web-серверы – те, которые намного меньше, чем Apache. Приложения такого размера могут уместиться в голове обычного человека; их работу можно представить себе систематически и строго, чтобы строго доказать их безопасность или масштабируемость. К числу очень маленьких Web-серверов относятся:

  • Cheetah Server, содержащий менее тысячи строк на C.
  • DustMote, очень маленький Web-сервер, реализованный в одном Tcl-исходнике размером примерно 3000 байт.
  • fnord занимает менее 20K, в зависимости от платформы и конфигурации. Несмотря на маленький размер, он поддерживает виртуальный хостинг, CGI и keep-alive.
  • ihttpd, имея менее 800 строчек C, умеет обслуживать страницы, включая CGI, посредством inetd.
  • mattows поддерживает CGI, насчитывая при этом всего лишь 600 строк на C.
  • Scrinchy, несмотря на маленький размер - около 30 KB - поддерживает примечательно много языков сценариев, включая специализированный стековый язык под названием Sy.
  • ZWS показывает, как можно написать содержательное приложение – в данном случае сервер HTTP 0.9+ – немногим более чем из 500 строк хорошо откомментированного zsh (!).
Маленький размер не препятствует серьёзному использованию этих серверов; fnord, например, обслуживает тысячи одновременных соединений.

Возможно, наиболее впечатляющая категория легких серверов по достижениям – высокопроизводительные серверы:

  • cghttpd – минимальный Web-сервер, который можно рассматривать как эксперимент по использованию асинхронных средств, доступных в ядрах Linux серии 2.6.
  • darkhttpd – быстрый однопоточный сервер HTTP/1.1.
  • Gatling специально разработан для высокой производительности. Поддерживает FTP, IPv6, виртуальный хостинг, CGI и т.п.
  • Kernux – модуль ядра Linux, который обеспечивает выполнение HTTP-демона.
  • lighttpd – пятый по популярности Web-сервер в мире (и его доля растет!). Он оптимизирован под большое количество одновременных соединений: "Типичный сценарий – использование lighttpd как сервера, разгружающего основной сервер, для выдачи статического контента..."
  • LiteSpeed Web Server – коммерческий лёгкий Web-сервер, в котором особый упор сделан на производительность и безопасность. LiteSpeed Technologies Inc. заявляет об ускорении в шесть раз для статического контента и несколько более скромных показателях для интерпретируемых страниц.
  • Miniature JWS, известный также как tjws - написанный на Java Web-сервер, который обрабатывает сервлеты, JSP и тысячи параллельных соединений, занимая 77 килобайт. Его автор характеризует его так: "на 10% быстрее, чем Apache 2.x."
  • Yaws – высокопроизводительный сервер HTTP/1.1, написанный на Erlang.

Многие Web-серверы реализованы как классы или библиотеки, разработанные для встраивания в большие приложения. Среди них особенно интересны:

  • EHS – "встраиваемый HTTP сервер," класс C++, разработанный для встраивания в большие C++ приложения; и
  • Embedded TCL Web Server, простейший Web-сервер, поддерживающий SSL и Basic Authentication и при этом фантастически быстрый – по замерам автора, не менее быстрый, чем lighttpd и AOLserver. Содержит меньше сотни строк Tcl.

На языке Python реализованы несколько Web-серверов, которые заполняют необычные ниши, в том числе:

  • cdServer - маленький простой http-сервер на Python, "разработанный для выдачи (статического) контента с CD-ROM". ??меет ограниченные возможности в обслуживании динамического контента. У нас есть несколько проектов, которые включают доставку непортящихся "live CD", и инструменты типа cdServer являются для них критическими.
  • edna – остроумный MP3-сервер на Python, основанный на HTTP.

Есть и другие интересные лёгкие Web-серверы, реализованные на Perl и на других, не так хорошо известных, языках:

  • Camlserv – полный Web-сервер, написанный на ocaml и нацеленный на "высокоинтерактивные Web-страницы". Умещается в нескольких тысячах строчек ocaml, большинство из которых посвящено специальным возможностям работы с MySQL и HTML.
  • dhttpd протоколирует обращения в том же формате, что и Apache. ??меет встроенный Perl-интерпретатор для поддержки CGI, виртуальный хостинг, IPv6, управление пропускной способностью и возможности безопасности.
  • DNHTTPD написан на Perl для UNIX®. Он поддерживает виртуальные хосты, SSL соединения, CGI и другое.
  • Jellybean – написанный на Perl сервер Perl Object Server, основанный на HTTP.
  • lns.http – общая Web-среда на LISP HTTP/1.1.
  • Mongrel – библиотека и сервер для HTTP, написанные на Ruby.
  • Nanoweb – быстрый, устойчивый Web-сервер, написанный на PHP. ??меет обширный список возможностей, включая полное соответствие HTTP/1.1, контроль обращений, аутентификацию, виртуальный хостинг, SSL совместимость и т.д.
  • Naridesh – написанный на Perl Web-сервер.
  • OpenAngel – написан на Perl. Его фокус – безопасность.
  • Xavante – HTTP/1.1 Web-сервер, написанный на Lua.
  • XSP написан на C# и выполняет роль ведущего узла ASP.NET.

Однажды вам могут понадобиться и некоторые другие написанные на C лёгкие Web-серверы с необычными дополнительными возможностями:

  • ABYSS переносим между UNIX и Win32 и претендует на то, чтобы "быть полностью HTTP/1.1-совместимым Web-сервером". Экономичен в использовании памяти.
  • Anti-Web HTTPD (также "Anti-Web", "awhttpd" и "AW") однопроцессный (не многопоточный), поддерживающий CGI сервер, в котором особое внимание уделено безопасности и простоте.
  • MHTTPD поддерживает MHTTPD Basic Authentication как из внешнего файла, так и при помощи LDAP-сервера.
  • mini-httpd обрабатывает параллельные запросы в одном потоке и нетребователен к хосту в плане памяти и процессора.
  • Naken Web похож на множество других лёгких серверов – поддерживает Basic Authentication, статический контент и т.д. – но авторы нацеливали его на операции для Web-камер и применяли на Gumstix, WRT54GL, OpenWrt и других инновационных платформах.
  • Null httpd – многопоточный, но простой и портативный Web-сервер.
  • Seminole – коммерческий Web-сервер, не требует много памяти и имеет много возможностей.
  • thttpd поддерживает регулирование пропускной способности, реализует chroot, Basic Authentication и т.д.

Ппроект Anti-Web HTTPD , который лежит на http://www.hcsw.org/awhttpd/ , мы сейчас и рассмотрим подробнее.

Исходники лежат тут

В юниксе существуют несколько моделей ввода-вывода : блокируемый , неблокируемый , мультиплексированный. В этом проекте используется мультиплексированный подход на основе функции select, при этом загрузка процессора происходит лишь в те моменты , когда обслуживаются клиентские I/O.

Системная функция select имеет 5 параметров -

 		1 максимальное число дескрипторов 
 		2 дескриптор чтения 
 		3 дескриптор записи 
 		4 дескриптор  ошибок 
 		5 тайм-аут
 
Принцип работы системного вызова select основан на обработке 4 типов событий : чтение сокета , запись сокета, обработка исключения и обработка тайм-аута. Функция select возвращает число дескрипторов , при этом оно может быть равно : либо >0, либо 0 в случае таймаута , либо -1 в случае ошибки.

Программная реализация :
для коннектов выделены 2 связных списка - use и free. Если при коннекте нет свободных free , с помощью malloc генерит еще один free,инициализирует ее и переводит в список use. При закрытии коннекта закрываются все его дескрипторы и он возвращается назад в список free.

Выборочные параметры конфига :

 	1 listen  - слушающий порт или список портов
 	2 maxusers 		- максимальное число одновременных коннектов
 	3 usertimeout   - тайм-аут в секундах
 
Порядок сборки и установки :
  make
  Положить бинарник myhttpd и конфиг myhttpd.conf в каталог /usr/local/sbin
  Запуск : /usr/local/sbin/myhttpd /usr/local/www 80
 
Порядок инициализации сервера при запуске
 	1 Инициализируется список free из 10 структур - initlists()
 	2 Инициализируется строка webroot как корневой веб-узел
 	3 Инициализация конфига - сначала defaultconfvals() , потом procconf()
 	4 Создаем список корневых документов - addindex("index.html");
 	5 Создаем массив сокет-дескрипторов servers - addtoservers() - также простой связанный список
 	6 Создаются обработчики для прерываний SIGINT,SIGQUIT,SIGTERM,SIGCHLD
 	7 Управление передается главному циклу selectloop
 
В главном цикле работает системный вызов select , при этом :
 	1 Если коннект просрочен - удаляем его из списка use
 	2 Проверяется статус коннекта - либо читаем из него , либо посылаем в него
 	3 Проверяем , есть ли новые коннекты , и если есть , то добавляем
 
Рассмотрим более подробно , что происходит в главном цикле - функция selectloop() (net.c)

 
 void selectloop() {
   fd_set rfds, wfds;
   struct connstruct *tp, *to;
   struct serverstruct *sp;
   int rnum, rnum2, wnum, active;
   int currtime;
   int count = 0 ;	
   
 
 
   while(1) {   // MAIN SELECT LOOP
     FD_ZERO(&rfds);
     FD_ZERO(&wfds);
     rnum = wnum = -1;
 
     // Add the listening sockets
     sp = servers;
     while(sp != NULL) {
       FD_SET(sp->sd, &rfds);
       if (sp->sd > rnum) rnum = sp->sd;
       sp = sp->next;
     }
 
     // Add the established sockets
     tp = usedconns;
     currtime = time(NULL);
     while(tp != NULL) {
 
       if (istimedout(tp, currtime)) {
         to = tp;
         tp = tp->next;
         removeconnection(to);
         continue;
       }
 
       if (tp->state == STATE_WANT_TO_READ_HEAD) {
         FD_SET(tp->networkdesc, &rfds);
         if (tp->networkdesc > rnum) rnum = tp->networkdesc;
       }
       if (tp->state == STATE_WANT_TO_SEND_HEAD) {
         FD_SET(tp->networkdesc, &wfds);
         if (tp->networkdesc > wnum) wnum = tp->networkdesc;
       }
       if (tp->state == STATE_WANT_TO_READ_FILE) {
         FD_SET(tp->filedesc, &rfds);
         if (tp->filedesc > rnum) rnum = tp->filedesc;
       }
       if (tp->state == STATE_WANT_TO_SEND_FILE) {
         FD_SET(tp->networkdesc, &wfds);
         if (tp->networkdesc > wnum) wnum = tp->networkdesc;
       }
       if (tp->state == STATE_DOING_DIR) {
         FD_SET(tp->networkdesc, &wfds);
         if (tp->networkdesc > wnum) wnum = tp->networkdesc;
       }
       tp = tp->next;
     }
 
     //active = select(4, &rfds, &wfds, NULL, NULL);
     active = select(wnum > rnum ? wnum+1 : rnum+1,
                     rnum != -1 ? &rfds : NULL,
                     wnum != -1 ? &wfds : NULL,
                     NULL, NULL);
 
     // Handle the listening sockets
     sp = servers;
     while(active > 0 && sp != NULL) {
       if (FD_ISSET(sp->sd, &rfds)) 
 	  {
 		handlenewconnection(sp->sd);
         active--;
       }
       sp = sp->next;
     }
 
     // Handle the established sockets
     tp = usedconns;
     currtime = time(NULL);
     while(active > 0 && tp != NULL) {
       to = tp;
       tp = tp->next;
 
       if (to->state == STATE_WANT_TO_READ_HEAD)
         if (FD_ISSET(to->networkdesc, &rfds)) 
 		{
           updatetimeout(to, currtime);
           active--;
           procreadhead(to);
         } 
       if (to->state == STATE_WANT_TO_SEND_HEAD)
         if (FD_ISSET(to->networkdesc, &wfds)) 
 		{
           updatetimeout(to, currtime);
           active--;
           procsendhead(to);
         } 
       if (to->state == STATE_WANT_TO_READ_FILE)
         if (FD_ISSET(to->filedesc, &rfds)) 
 		{
           updatetimeout(to, currtime);
           active--;
           procreadfile(to);
         } 
       if (to->state == STATE_WANT_TO_SEND_FILE)
         if (FD_ISSET(to->networkdesc, &wfds)) 
 		{
           updatetimeout(to, currtime);
           active--;
           procsendfile(to);
         }
       if (to->state == STATE_DOING_DIR)
         if (FD_ISSET(to->networkdesc, &wfds)) {
           updatetimeout(to, currtime);
           active--;
           procdodir(to);
         }
     }
 
 	count ++;
    syslog(LOG_INFO,"=================count= %d",count);	
 
   }  // MAIN SELECT LOOP
 
Если в броузер загрузить документ по адресу http://localhost/index.html , то цикл отработает 5 итераций , на каждой итерации будет проверяться статус запроса :

1 Как только приходит запрос , мы записываем дескриптор в массив servers , который есть ни что иное, как массив числовых дескрипторов. И вызываем метод handlenewconnection : в ней происходит системный вызов accept. Если accept возвращает целочисленный дескриптор , больший нуля , это говорит о том , что сокет готов для прослушивания . Вызывается метод addconnection , передавая ему в качестве параметра чиловой дескриптор (напр. 7) , который вернул вызов accept , при этом берется структура из списка free , ее поле networkdesc становится равным 7 , статус - STATE_WANT_TO_READ_HEAD , и эта структура переводится в список use.

2 Делаем вызов procreadhead - в ней происходит системный вызов read , читается буфер заголовка http-запроса , значение которого может быть примерно таким : Jul 23 13:23:16 linux-b4n8 myhttpd: procreadhead buf= GET /index.html HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.3) ... при этом статус коннекта становится = STATE_WANT_TO_SEND_HEAD

3 Делаем вызов procsendhead , в ней сначала проверяем 404 ошибку , затем формируем http-заголовок , пишем его с помощью системного вызова write в выходной поток, при этом он может быть таким : HTTP/1.1 200 OK MyHttpd Server: ... Content-Type: ... Content-Length: ... ... при этом статус коннекта становится = STATE_WANT_TO_READ_FILE

4 Делаем вызов procreadfile - читаем с помощью системного вызова read содержимое запрашиваемого url , которое пишем в поле cn->databuf При этом статус становится = STATE_WANT_TO_SEND_FILE

5 Делаем вызов procsendfile - с помощью системного вызова write пишем в выходной поток сокета содержимое cn->databuf

Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье