Здравствуйте!
Задача:
Создать приложение демон-процесс, слушающий и обрабатывающий запросы к TCP порту основанные на HTTP, выдающий в результате обработки запроса HTML-контент взятый из базы данных mysql, выполняющий перекодирование выдаваемого контента в желаемую/затребованную кодировку, которая устанавливается либо в самом запросе, либо в настройках его инициализационных параметров.
К сожалению, никогда не писал С++ программ для работы в сети, поэтому не представляю себе, что и в какой последовательности работает.
Я написал следующую программу:
int main (int argc, char * const argv[]) {
struct sockaddr_in addr_info;
int add_len = sizeof(addr_info);
int ret_addr, sock_id;
char* buf = new char[256];
Но я так понимаю, что это совсем не в ту сторону. Единственное, что тут правильно — это socket().
Пожалуйста, подскажите схему приложения-реализации данной задачи, что за чем следует, а я постараюсь по Вашей схеме написать реализацию.
Заранее благодарен.
Алексей
28.09.11 13:56: Перенесено модератором из 'C/C++' — Odi$$ey
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Здравствуйте, Handler, Вы писали:
H>К сожалению, никогда не писал С++ программ
в вашем коде, из с++, только new и cout. так что программа написана на Си.
смотрите boost.asio.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Возьмите книжку Стивенса по сетевым приложениям.
Прочитайте оттуда буквально три первые главы (100 стр.) — и все вопросы отпадут.
PS: boost.asio смотреть рано.
0) болт кладем на вух ораторов выше( пока руками не научитесь пользоваться — обертки будут лишь дурманющим разум зельмем ).
1) в гугле вбиваем "пример TCP сервер linux".
2) прогоняем через ман каждую функцию.
В качестве подсказки:
{
int server_sock = socket( ... ); // собственно создаем дескриптор серверного сокета.
...
bind( ... ); // связываем определенный адрес с сокетом - в примере это 0.0.0.0:8080.
...
listen( ... ); // врубаем механизм.
...
// Теперь нужно принять подключение:int client_sock = accept( ... );
// ^^^^^^
// вот это клиентский сокет. для чтения и писанины скрещивать его с функциями read/write.
...
close( client_sock ); // все в имени моем.
...
close( server_sock ); // ----- // -----
}
Меня смущает тот факт, что все примеры, которые я встречал, описывают клиент-серверную модель, а мне, скорее всего нужна модель типа tcpdump.
Спасибо, что дали направление
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Здравствуйте, pavard, Вы писали: P>0) болт кладем на вух ораторов выше( пока руками не научитесь пользоваться — обертки будут лишь дурманющим разум зельмем ).
ох уж эти велокодеры.. они такие забавные 8)
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Нет такой модели tcpdump. Отдавать контент по хттп — дело сервера, запрашивать этот контент — дело клиента. Отсюда и название клиент-серверное.
Название tcpdump = tcp + dump = сдампь чтоб я посмотрел что там бегает = тупо утилита чтоб посмотреть.
В общем, проще будет пойти от главного — разобраться в целях. И зрите не в список целей написать то-то то-то, а в список — я не понимаю того-то того-то.
Здравствуйте, Handler, Вы писали:
H>Задача: H>Создать приложение демон-процесс, слушающий и обрабатывающий запросы к TCP порту основанные на HTTP, выдающий в результате обработки запроса HTML-контент взятый из базы данных mysql, выполняющий перекодирование выдаваемого контента в желаемую/затребованную кодировку, которая устанавливается либо в самом запросе, либо в настройках его инициализационных параметров. H>К сожалению, никогда не писал С++ программ для работы в сети, поэтому не представляю себе, что и в какой последовательности работает. H>Пожалуйста, подскажите схему приложения-реализации данной задачи, что за чем следует, а я постараюсь по Вашей схеме написать реализацию.
Слишком крутой заложен вираж.
Если сетевые приложения до этого никогда не писались, то сразу реализовать такой конвейер, — а тут и
работа с TCP, и обработка HTTP, и работа с кодировками, и база данных, — будет непросто.
В целях обучения лучше разбить эту задачу на составляющие и попытаться освоить их изолированно друг от друга.
Для начала разобраться с TCP/IP, научиться писать простые клиент-серверы и передавать сообщения, а
также корректно размыкать соединения. По TCP есть несколько неплохих книжек.
Потом понять, какие места занимают TCP и HTTP в стеке OSI.
HTTP тоже крепкий орешек, лучше всего скачать последние RFC (1.0/1.1) и вызубрить их от корки до корки, а
еще найти хорошую книгу по этому протоколу. Потом уже можно пытаться писать свой HTTP-сервер и стучаться к
нему из браузера. Отдельное место в этом всем занимает вопрос производительности и масштабируемости.
По ходу изучения будут возникать всякие нюансы и тонкости, которые и сформируют определенные знания о
том, как на самом деле работают веб-клиенты и веб-серверы. А тонкостей будет много.
Ну и только после этого можно садиться и писать веб-приложения.
P.S.
Простой HTTP-сервер можно написать примерно так:
Но это будет работать только для очень ограниченного диапазона HTTP-запросов и это не
учитывает всякие тонкости HTTP — persistent connections, request pipelining, content-coding, multipart и т.п.
Фантастика!
Думаю, Вы абсолютно правы.
Во всяком случае, Вы сейчас логику многих вещей разъяснили.
Вос всяком случае я еще немного по-спрашиваю Вас:
Если мы слушаем http-port, мы должны выключить веб-сервер, запущенный на этой же машине, и я понимаю, почему. Но меня смущает тот факт, например, что в это же время наш ( и не только наш) протокол слушает iptables (netflter). Возможно, они могут слушать его одновременно потому, что netfilter работает в ядре, тогда как быть с tcpdump? Получается, tcpdump может слушать вместе с apache, а моя программа — нет?
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Здравствуйте, Handler, Вы писали:
H>Фантастика! H>Думаю, Вы абсолютно правы. H>Во всяком случае, Вы сейчас логику многих вещей разъяснили. H>Вос всяком случае я еще немного по-спрашиваю Вас: H>Если мы слушаем http-port, мы должны выключить веб-сервер, запущенный на этой же машине, и я понимаю, почему. Но меня смущает тот факт, например, что в это же время наш ( и не только наш) протокол слушает iptables (netflter). Возможно, они могут слушать его одновременно потому, что netfilter работает в ядре, тогда как быть с tcpdump? Получается, tcpdump может слушать вместе с apache, а моя программа — нет?
У вас не верное представление о том что как работает и за что отвечает. Лучше будет если для какждой подсистемы вы сами хоть поверхностное описание прочитаете — это выработает в вас навок чтение документации и вылечет додумывание...
В общем настроение побольтать, поэтому метафора:
Представим ваш железный сервер — министерство.
Один из начальников — логика( скрипт ).
Секретарша — хттп-сервер .
Проходная и охрана — фаервол.
Курьер — TCP-сессия.
Действие.
Итак клиент делает запрос — отсылает курьера с листочком к начальнику в котором написано:
GET /document_about.html HTTP/1.1
Host: boss112.ministerstvo.ru
Курьер проходжит вначале на проходную( фаерволл ), — тут его шманают смотрят на него и могут либо пропустить, либо не пропустить — если к примеру на фаерволе есть правило никого из Быдло и Со не пропускать. В листочек притом не заглядывают — это не их пререгатива.
Дальше курьер шагает в открытый порт( дверь ) к секретарше и вручает ей запрос.
Секретарша смотрит на него и отвечает:
если босса нет на месте:
HTTP/1.1 404 Not Found
если босс бухой в сраку и несет белеберду:
HTTP/1.1 500 Internal Server Error
если босс в норме:
HTTP/1.1 200 Ok
"тело ответа"
или вообще может перенаправить( не помню код ) в другую дверь или министерство.
курьер несется назад с ответом...
Сказке конец.
Мораль:
— фаервол ничего нигде не слушает, а лишь пропускает или не пропускает на основе выданного ему предписания.
— тцпдампа в этой сказке нет — тк это видиокамеры, через которые админ может посмотреть что и куда бегает, но не может ответить вместо или подменить ответ.
— секретарша принимает записку не от охраны а от курьера напрямую — тцп сессия открывается с сервером, а не с фаерволлом.
— дальнейшие выводы делайте из документации.
Я буду Ваш ответ показывать как анекдот (в хорошем смысле).
По поводу ipatbles and tcpdump — был не прав, понял, что работают на разных уровнях модели OSI.
Кстати, кто на каких?
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Здравствуйте, Handler, Вы писали:
H>Я буду Ваш ответ показывать как анекдот (в хорошем смысле). H>По поводу ipatbles and tcpdump — был не прав, понял, что работают на разных уровнях модели OSI. H>Кстати, кто на каких?
Здравствуйте, Handler, Вы писали:
H>Если мы слушаем http-port, мы должны выключить веб-сервер, запущенный на этой же машине, и я понимаю, почему.
Да, но только если используется один и тот же порт. Это, думаю, понятно.
H>Но меня смущает тот факт, например, что в это же время наш ( и не только наш) протокол слушает iptables (netflter). Возможно, они могут слушать его одновременно потому, что netfilter работает в ядре, тогда как быть с tcpdump? Получается, tcpdump может слушать вместе с apache, а моя программа — нет?
Всякие прозрачные прокси-серверы и фаерволы, контролирующие прохождение данных по сети,
формально не являются частью модели OSI (хотя их присутствие сказывается на жизнеспособности
сети самым критическим образом).
И потом, прослушка протоколов может быть реализована очень хитрыми методами и на разных уровнях,
от прикладного до самых низких, и для этого вовсе необязательно создавать слушающий порт.
Я не специалист по *nix-системам, но в Windows, к примеру, путей много, вплоть до хаков ядра.
Поэтому то, что какой-то security-продукт свободно мониторит деятельность вашего сокета, не
будучи подсоединенным к нему, беспокоить не должно.
Тогда возникает закономерный вопрос: Зачем нам создавать пор, если мы можем поступать подобно прослушке? Таким образом, конечное решение зависит лишь от метода, который нам больше по душе
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Здравствуйте, Handler, Вы писали:
H>Тогда возникает закономерный вопрос: Зачем нам создавать пор, если мы можем поступать подобно прослушке? Таким образом, конечное решение зависит лишь от метода, который нам больше по душе
Разница в сложности реализации.
Создать сокет, перевести его в слушающий режим и принимать коннекты — это одно.
А написать полноценный сниффер или перехватчик трафика — это совсем другое.
Здравствуйте, Handler, Вы писали:
H>Тогда возникает закономерный вопрос: Зачем нам создавать пор, если мы можем поступать подобно прослушке? Таким образом, конечное решение зависит лишь от метода, который нам больше по душе
Вопросы человека напрочь игнорирующего документацию, и любящего окружающих. ***бали филосовствовать на тему... напишите хоть что-то, потом рассуждайте.
Для работы с сокетом нужно дергать несколько функций — открыть/закрыть, прочитать/записать( в первом приближении ). И не заботиться о гарантии доставке, целостности данных, фрагментации/дефрагментации, источнике/получателе, очередности, буферизации, приоритете, таймаутах, ... . Все ясно: коннект есть пока нет ошибок — пишем/читам.
Для создания подобия прослушки — с опусканием хотябы на один уровень должны будете для начала реализовать стек тцп( со всеми подсистемами ), еще ниже — стек ип( на все не менее нескольких месяцев ), + отладка и баги. В итоге получите те-же функции, + кучу потерянного времени и ящик неотловленных багов.
Нахрена делать то что уже за вас сделали и отладили, портировали на учу платформ, дали функции и хорошо описали все в документации на многих языках, включая русский.
Все-равно что пристрелить курьера и заставить секретаршу бегать ко всем клиентам самостоятельно.
int main (int argc, char * const argv[]) {
struct sockaddr_in addr_info;
int add_len = sizeof(addr_info);
int ret_addr, sock, n;
char* buf = new char[256];
Даже не могу сказать, что в ней не работает.
Если запускать в отладчике — то виснет на accept.
Если просто запустить — выполняется, ничего не происходит, не заканчивается.
Внутренний веб-сервер остановлен, обращаюсь к внутреннему хосту, а также к любому внешнему из браузера во время работы программы — ничего.
Когда мы указываем порт и адрес в структуре — их обязательно переводить функциями, или можно указать, как в моей программе?
И еще: как указать :
локальный хост?
конкретный хост?
Любой хост?
Пока все.
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Наконец-то заработало.
Здесь приведен участок кода, в котором программа слушает http-порт и читает данные, которые посылает ей браузер, если ему указать localhost, и затем делается попытка послать ответ браузеру (char* reply = "HTTP/1.1 403 Forbidden\r\n\0"