C++ listen tcp socket
От: Handler Украина  
Дата: 27.09.11 23:22
Оценка:
Здравствуйте!
Задача:
Создать приложение демон-процесс, слушающий и обрабатывающий запросы к 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];

bzero(&addr_info, sizeof(addr_info));
addr_info.sin_family = AF_INET;
addr_info.sin_port = 8080;
addr_info.sin_addr.s_addr = INADDR_ANY;

sock_id = socket(AF_INET, SOCK_STREAM, 0);
if (sock_id==-1) {cout<< "Error create socket\n"; return -1;}
if (bind(sock_id, (struct sockaddr*)&addr_info, sizeof(addr_info))==-1) {cout<< "Error bind\n"; return -1;}
listen(sock_id, 5);
ret_addr = recv(sock_id, buf, 256, 0);
// ret_addr = accept(sock_id, (struct sockaddr*)&addr_info, (socklen_t*)&add_len);
return 0;
}

Но я так понимаю, что это совсем не в ту сторону. Единственное, что тут правильно — это socket().
Пожалуйста, подскажите схему приложения-реализации данной задачи, что за чем следует, а я постараюсь по Вашей схеме написать реализацию.
Заранее благодарен.
Алексей

28.09.11 13:56: Перенесено модератором из 'C/C++' — Odi$$ey
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Re: C++ listen tcp socket
От: niXman Ниоткуда https://github.com/niXman
Дата: 27.09.11 23:58
Оценка:
Здравствуйте, Handler, Вы писали:

H>К сожалению, никогда не писал С++ программ

в вашем коде, из с++, только new и cout. так что программа написана на Си.
смотрите boost.asio.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: C++ listen tcp socket
От: placement_new  
Дата: 28.09.11 02:49
Оценка:
Здравствуйте, Handler, Вы писали:

Возьмите книжку Стивенса по сетевым приложениям.
Прочитайте оттуда буквально три первые главы (100 стр.) — и все вопросы отпадут.
PS: boost.asio смотреть рано.
Re: C++ listen tcp socket
От: pavard  
Дата: 28.09.11 06:12
Оценка: :)
весь инет засрали этим вопросом.

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 ); // ----- // -----
}
Re: C++ listen tcp socket
От: Handler Украина  
Дата: 28.09.11 09:32
Оценка:
Меня смущает тот факт, что все примеры, которые я встречал, описывают клиент-серверную модель, а мне, скорее всего нужна модель типа tcpdump.
Спасибо, что дали направление
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Re[2]: C++ listen tcp socket
От: niXman Ниоткуда https://github.com/niXman
Дата: 28.09.11 09:33
Оценка:
Здравствуйте, pavard, Вы писали:
P>0) болт кладем на вух ораторов выше( пока руками не научитесь пользоваться — обертки будут лишь дурманющим разум зельмем ).
ох уж эти велокодеры.. они такие забавные 8)
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: C++ listen tcp socket
От: pavard  
Дата: 28.09.11 11:46
Оценка:
Вердикт — сами не знаете что хотите.

Нет такой модели tcpdump. Отдавать контент по хттп — дело сервера, запрашивать этот контент — дело клиента. Отсюда и название клиент-серверное.
Название tcpdump = tcp + dump = сдампь чтоб я посмотрел что там бегает = тупо утилита чтоб посмотреть.

В общем, проще будет пойти от главного — разобраться в целях. И зрите не в список целей написать то-то то-то, а в список — я не понимаю того-то того-то.
Re: C++ listen tcp socket
От: okman Беларусь https://searchinform.ru/
Дата: 28.09.11 12:27
Оценка:
Здравствуйте, 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-сервер можно написать примерно так:
SOCKET Sock = socket(...);
bind(Sock, ...);
listen(Sock, ...);

SOCKET AccSock = accept(Sock, ...);
recv(AccSock, pBuffer, ...);
//...
send(AccSock, "HTTP/1.0 200 OK\r\n\r\nContent-Type:text/html\r\nContent-Length: 53\r\n\r\n<html><head></head><body><h1>Hello</h1></body></html>", ...);
shutdown(AccSock, SD_SEND);
closesocket(AccSock);
closesocket(Sock);


Но это будет работать только для очень ограниченного диапазона HTTP-запросов и это не
учитывает всякие тонкости HTTP — persistent connections, request pipelining, content-coding, multipart и т.п.
Re[2]: C++ listen tcp socket
От: Handler Украина  
Дата: 29.09.11 06:08
Оценка:
Фантастика!
Думаю, Вы абсолютно правы.
Во всяком случае, Вы сейчас логику многих вещей разъяснили.
Вос всяком случае я еще немного по-спрашиваю Вас:
Если мы слушаем http-port, мы должны выключить веб-сервер, запущенный на этой же машине, и я понимаю, почему. Но меня смущает тот факт, например, что в это же время наш ( и не только наш) протокол слушает iptables (netflter). Возможно, они могут слушать его одновременно потому, что netfilter работает в ядре, тогда как быть с tcpdump? Получается, tcpdump может слушать вместе с apache, а моя программа — нет?
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Re[3]: C++ listen tcp socket
От: pavard  
Дата: 29.09.11 09:16
Оценка:
Здравствуйте, 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

"тело ответа"


или вообще может перенаправить( не помню код ) в другую дверь или министерство.

курьер несется назад с ответом...

Сказке конец.

Мораль:
— фаервол ничего нигде не слушает, а лишь пропускает или не пропускает на основе выданного ему предписания.
— тцпдампа в этой сказке нет — тк это видиокамеры, через которые админ может посмотреть что и куда бегает, но не может ответить вместо или подменить ответ.
— секретарша принимает записку не от охраны а от курьера напрямую — тцп сессия открывается с сервером, а не с фаерволлом.
— дальнейшие выводы делайте из документации.
Re[4]: C++ listen tcp socket
От: Handler Украина  
Дата: 29.09.11 09:22
Оценка:
Я буду Ваш ответ показывать как анекдот (в хорошем смысле).
По поводу ipatbles and tcpdump — был не прав, понял, что работают на разных уровнях модели OSI.
Кстати, кто на каких?
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Re[5]: C++ listen tcp socket
От: pavard  
Дата: 29.09.11 09:31
Оценка:
Здравствуйте, Handler, Вы писали:

H>Я буду Ваш ответ показывать как анекдот (в хорошем смысле).

H>По поводу ipatbles and tcpdump — был не прав, понял, что работают на разных уровнях модели OSI.
H>Кстати, кто на каких?

rtfm.
Re[3]: C++ listen tcp socket
От: okman Беларусь https://searchinform.ru/
Дата: 29.09.11 10:11
Оценка:
Здравствуйте, Handler, Вы писали:

H>Если мы слушаем http-port, мы должны выключить веб-сервер, запущенный на этой же машине, и я понимаю, почему.


Да, но только если используется один и тот же порт. Это, думаю, понятно.

H>Но меня смущает тот факт, например, что в это же время наш ( и не только наш) протокол слушает iptables (netflter). Возможно, они могут слушать его одновременно потому, что netfilter работает в ядре, тогда как быть с tcpdump? Получается, tcpdump может слушать вместе с apache, а моя программа — нет?


Всякие прозрачные прокси-серверы и фаерволы, контролирующие прохождение данных по сети,
формально не являются частью модели OSI (хотя их присутствие сказывается на жизнеспособности
сети самым критическим образом).

И потом, прослушка протоколов может быть реализована очень хитрыми методами и на разных уровнях,
от прикладного до самых низких, и для этого вовсе необязательно создавать слушающий порт.
Я не специалист по *nix-системам, но в Windows, к примеру, путей много, вплоть до хаков ядра.
Поэтому то, что какой-то security-продукт свободно мониторит деятельность вашего сокета, не
будучи подсоединенным к нему, беспокоить не должно.
Re[4]: C++ listen tcp socket
От: Handler Украина  
Дата: 30.09.11 09:37
Оценка:
Тогда возникает закономерный вопрос: Зачем нам создавать пор, если мы можем поступать подобно прослушке? Таким образом, конечное решение зависит лишь от метода, который нам больше по душе
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Re[5]: C++ listen tcp socket
От: okman Беларусь https://searchinform.ru/
Дата: 30.09.11 09:44
Оценка:
Здравствуйте, Handler, Вы писали:

H>Тогда возникает закономерный вопрос: Зачем нам создавать пор, если мы можем поступать подобно прослушке? Таким образом, конечное решение зависит лишь от метода, который нам больше по душе


Разница в сложности реализации.
Создать сокет, перевести его в слушающий режим и принимать коннекты — это одно.
А написать полноценный сниффер или перехватчик трафика — это совсем другое.
Re[5]: C++ listen tcp socket
От: pavard  
Дата: 30.09.11 12:22
Оценка:
Здравствуйте, Handler, Вы писали:

H>Тогда возникает закономерный вопрос: Зачем нам создавать пор, если мы можем поступать подобно прослушке? Таким образом, конечное решение зависит лишь от метода, который нам больше по душе


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

Для работы с сокетом нужно дергать несколько функций — открыть/закрыть, прочитать/записать( в первом приближении ). И не заботиться о гарантии доставке, целостности данных, фрагментации/дефрагментации, источнике/получателе, очередности, буферизации, приоритете, таймаутах, ... . Все ясно: коннект есть пока нет ошибок — пишем/читам.

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

Нахрена делать то что уже за вас сделали и отладили, портировали на учу платформ, дали функции и хорошо описали все в документации на многих языках, включая русский.

Все-равно что пристрелить курьера и заставить секретаршу бегать ко всем клиентам самостоятельно.
Re[6]: C++ listen tcp socket
От: Handler Украина  
Дата: 04.10.11 01:13
Оценка:
Вот моя программа:
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

using namespace std;

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];

// socket
bzero(&addr_info, sizeof(addr_info));
addr_info.sin_family = AF_INET;
addr_info.sin_port = 80;
addr_info.sin_addr.s_addr = inet_addr("127.0.0.1");//INADDR_ANY;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock==-1) {cout<< "Error create socket\n"; return -1;}
// bind
if (bind(sock, (struct sockaddr*)&addr_info, sizeof(addr_info))==-1) {cout<< "Error bind\n"; close(sock); return -1;}

// listen
if (!listen(sock, 5)) {
ret_addr = accept(sock, (struct sockaddr*)&addr_info, (socklen_t*)&add_len);
n = read(ret_addr, buf, 255);
// ret_addr = recv(sock, buf, 256, 0);
cout << buf << "\n";
}
else {
cout << "Error listen ";
}
close(sock);

return 0;
}

Даже не могу сказать, что в ней не работает.
Если запускать в отладчике — то виснет на accept.
Если просто запустить — выполняется, ничего не происходит, не заканчивается.
Внутренний веб-сервер остановлен, обращаюсь к внутреннему хосту, а также к любому внешнему из браузера во время работы программы — ничего.
Когда мы указываем порт и адрес в структуре — их обязательно переводить функциями, или можно указать, как в моей программе?
И еще: как указать :
локальный хост?
конкретный хост?
Любой хост?
Пока все.
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Re[7]: C++ listen tcp socket
От: pavard  
Дата: 04.10.11 12:07
Оценка:
Здравствуйте, Handler, Вы писали:

H>addr_info.sin_port = 80;

addr_info.sin_port = htons( 80 );

и проверте что программа запускается из под рута. в юнихах порты до 1024 может открывать только рут.
Re[8]: C++ listen tcp socket
От: Handler Украина  
Дата: 05.10.11 05:58
Оценка:
Наконец-то заработало.
Здесь приведен участок кода, в котором программа слушает http-порт и читает данные, которые посылает ей браузер, если ему указать localhost, и затем делается попытка послать ответ браузеру (char* reply = "HTTP/1.1 403 Forbidden\r\n\0"

if (!listen(sock, 5)) {
ret_addr = accept(sock, (struct sockaddr*)&addr_info, (socklen_t*)&add_len);
n = read(ret_addr, buf, 255);
buf[255] = '\0';
n = write(sock, reply, strlen(reply));
cout << errno << endl;
cout << buf << "\n";
}

чтение возвращает -1, errno=57 — Socket is not connected.
Что я делаю не так?
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Re[9]: C++ listen tcp socket
От: pavard  
Дата: 05.10.11 07:41
Оценка:
H>if (!listen(sock, 5)) {
H> ret_addr = accept(sock, (struct sockaddr*)&addr_info, (socklen_t*)&add_len);
H> n = read(ret_addr, buf, 255);
тут надо проверять на ошибку( n == -1 ) и брать errno — дальше она перетерается write'ом.

H> buf[255] = '\0';

buf[n]='\0';

H> n = write(sock, reply, strlen(reply));

первый параметр.

H> cout << errno << endl;

это ошибка от write.

H> cout << buf << "\n";

H>}

на сем заканчиваю что-либо отвечать в этом посте.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.