Вот это да! Почему все так просто оказалось? -lboost_system решил проблему. Не перестаю удивлять окружающих своей тупостью, впрочем, и себя тоже.
Спасибо.
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Здравствуйте, Handler, Вы писали:
H>Вот это да! Почему все так просто оказалось? -lboost_system решил проблему. Не перестаю удивлять окружающих своей тупостью, впрочем, и себя тоже. H>Спасибо.
Хватит насиловать человека boost'ом.
Он в трех соснах (listen bind accept) сишных функциях заблудился и понятия не имеет ни про синхронность асинхронность многопоточность и т.п.
Ему Стивенса читать надо стивенс unix взаимодействие процессов стивенс unix разработка сетевых приложений
+ man epoll
Когда осилит — будет писать обёртки на С++ когда их осилит почитает про boost.asio
К сожалению, у меня со стивенсом не срослось — первый же пример не скомпилился
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Re[28]: C++ listen tcp socket
От:
Аноним
Дата:
13.10.11 06:44
Оценка:
Как ни прискорбно — но с boost у меня тоже не срослось.
Итак, вернемся к самописному варианту tcp-сервера.
Как утверждает Стивенс (и не зря утверждает), "сервер" начинает слушать протокол и порт, который мы ему "натравили":
listen();
И далее принимает(или "засыпает", если очередь входящих сообщений пуста) входящие запросы от "клиента" (в нашем случае — веб-браузера):
accept();
(Дальше мои мысли)
Следовательно, как только accept() вернул нам валидный дескриптор:
if ( (session=accept(socket, buf, buf_len))!=-1 ) {/*valid handler*/}
мы можем создавать дочерний поток(процесс), который обработает запрос и завершится:
Простите, поторопился я с выводами — представленная мной схема оказалась вполне работоспособной.
Теперь скажите мне, почему session закрывается родителем?
Я, конечно, ноль в многопоточности, однако из прочитанной мной литературы о процессах сделал вывод, что с момента
fork()
и родитель, и его потомок начинают работать одновременно в одном и том же адресном пространстве (за последнее не ручаюсь). Как же потомок сможет читать/писать в session, если родитель, согласно логике программы, сразу же закроет дескриптор?
Подскажите, пожалуйста, в каком месте нарушена логика?
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Здравствуйте, Handler, Вы писали:
H>Простите, поторопился я с выводами — представленная мной схема оказалась вполне работоспособной.
H>Теперь скажите мне, почему session закрывается родителем? H>Я, конечно, ноль в многопоточности, однако из прочитанной мной литературы о процессах сделал вывод, что с момента H>fork() H>и родитель, и его потомок начинают работать одновременно в одном и том же адресном пространстве (за последнее не ручаюсь). Как же потомок сможет читать/писать в session, если родитель, согласно логике программы, сразу же закроет дескриптор? H>Подскажите, пожалуйста, в каком месте нарушена логика?
открой для себя man
разные процессы живут в разных адресных пространствах
fork создаёт новый процесс
если хочешь одно адресное пространство тебе надо создавать поток(нить, thread) в том же процессе.
Вот мой эксперемент 3х-летеней давновсти. Дыр куча — не проект а решето
Взял первый же пример из boost.asio — date_time, который посылает клиенту ответ. Так вот, я не смог прочитать от клиента сообщение.
Однако, это не заставило меня отказаться от boost вообще — только сейчас мне важнее разобраться с сокетами и потоками:
Первым делом — самолеты, ну а девушки — потом...
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Здравствуйте, Handler, Вы писали:
H>не смог прочитать от клиента сообщение.
там ведь пара: клиент и сервер. примеры все рабочие. так что, этого не может быть.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, Handler, Вы писали:
H>Взял первый же пример из boost.asio — date_time, который посылает клиенту ответ. Так вот, я не смог прочитать от клиента сообщение. H>Однако, это не заставило меня отказаться от boost вообще — только сейчас мне важнее разобраться с сокетами и потоками: H>Первым делом — самолеты, ну а девушки — потом...
Есть не только date_time. Есть примеры http-серверов.
Теперь встал еще один вопрос: Как отправить заголовок браузеру? Т.е.:
в php ч/з header(), а в с++ — ?
Начнем с самого простого, без чего, якобы, браузер вообще не сможет прочитать содержимое ответа (но, тем не менее, читает) — Content-length:
string str = "<html>...</html>";
string reply = "Content-length: "+str.length();
reply+= "\r\n\r\n"; // end of header
reply+= str;
Здесь все отлично — браузер отображает содержимое документа, причем сам заголовок в теле документа не отображается.
Далее хочу отправить кодировку в документ, т.к. документ у меня в cp-1251, а браузер — в utf-8 (default):
Какой же параметр устанавливает кодировку в заголовке?
google.com -> http header rfc -> http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
Читаю:
14.2 Accept-Charset
Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
14.17 Content-Type
Content-Type: text/html; charset=ISO-8859-4
Пишу:
Здравствуйте, Handler, Вы писали:
H>Теперь встал еще один вопрос: Как отправить заголовок браузеру? Т.е.: H>в php ч/з header(), а в с++ — ? H>Начнем с самого простого, без чего, якобы, браузер вообще не сможет прочитать содержимое ответа (но, тем не менее, читает) — Content-length:
Без Content-Length и браузер, и сервер, считают закрытие соединения признаком конца сообщения.
Хотя так делать крайне не рекомендуется.
H>
H>string str = "<html>...</html>";
H>string reply = "Content-length: "+str.length();
H>reply+= "\r\n\r\n"; // end of header
H>reply+= str;
H>
А где статусная строка (HTTP/1.1 200 OK) ?
H>Здесь все отлично — браузер отображает содержимое документа, причем сам заголовок в теле документа не отображается. H>Далее хочу отправить кодировку в документ, т.к. документ у меня в cp-1251, а браузер — в utf-8 (default): H>Какой же параметр устанавливает кодировку в заголовке?
Клиент говорит серверу о том, в какой кодировке он желает получить ответ, с помощью Accept-Charset.
Сервер обозначает кодировку ответа внутри Content-Type. Например: "Content-Type: text/html; charset=utf-8".
Если кодировка не указывается, для HTML по умолчанию берется ISO-8859-1, а для XHTML — UTF-8.
H>Ни один из этих вариантов браузер не считает за заголовки и выводит их в основное тело документа. H>Как правильно и какие заголовки посылать браузеру?
Это потому, что Вы не читаете спецификацию, и, подозреваю, даже не заглядываете в предыдущие ответы темы.
А HTTP, между тем, не такой уж и примитивный протокол, и в нем не все лежит на поверхности.
Книги:
HTTP Developer's Handbook (C. Shiflett)
HTTP: The Definitive Guide (D. Gourley, B. Totty, M. Sayer, S. Reddy, A. Aggarwal)
Web-протоколы: теория и практика НТТР/1.1, взаимодействие протоколов, кэширование, измерение трафика
(Б. Кришнамурти, Дж. Рексфорд)
Все равно не видит кодировку.
O>Клиент говорит серверу о том, в какой кодировке он желает получить ответ, с помощью Accept-Charset. O>Сервер обозначает кодировку ответа внутри Content-Type. Например: "Content-Type: text/html; charset=utf-8". O>Если кодировка не указывается, для HTML по умолчанию берется ISO-8859-1, а для XHTML — UTF-8.
Вот что сервер получает от клиента:
GET / HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_4) AppleWebKit/535.1+ (KHTML, like Gecko) Version/5.0 Safari/533.16
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: uk-ua
Accept-Encoding: gzip, deflate
Connection: keep-alive
Сервер отдает документ с правильным содержимым Content-Type.
O>Начинать нужно было не с форума, а отсюда:
O>Спецификации: O>RFC 1945 (HTTP 0.9-1.0) O>RFC 2616 (HTTP 1.1)
O>Книги: O>HTTP Developer's Handbook (C. Shiflett) O>HTTP: The Definitive Guide (D. Gourley, B. Totty, M. Sayer, S. Reddy, A. Aggarwal) O>Web-протоколы: теория и практика НТТР/1.1, взаимодействие протоколов, кэширование, измерение трафика O>(Б. Кришнамурти, Дж. Рексфорд)
много текста — про способы передачи кодировки сервером клиенту, не известные мне ничего не написано
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Тут не хватает заголовка Content-Type c нужным charset-ом.
H>Вот что сервер получает от клиента:
H>GET / HTTP/1.1 H>Host: localhost:8080 H>User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_4) AppleWebKit/535.1+ (KHTML, like Gecko) Version/5.0 Safari/533.16 H>Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 H>Accept-Language: uk-ua H>Accept-Encoding: gzip, deflate H>Connection: keep-alive
O>Тут не хватает заголовка Content-Type c нужным charset-ом.
Вот я сейчас не понял — как и где его не хватает? В str он есть, а в заголовок его не надо писать.
H>>GET / HTTP/1.1 H>>Host: localhost:8080 H>>User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_4) AppleWebKit/535.1+ (KHTML, like Gecko) Version/5.0 Safari/533.16 H>>Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 H>>Accept-Language: uk-ua H>>Accept-Encoding: gzip, deflate H>>Connection: keep-alive
O>А тут не хватает заголовка Accept-Charset.
что мне клиент прислал, то я и показал- все вопросы к веб-браузеру. Да и как, собственно, браузер может требовать кодировку? Его дело — запрашивать документ и отображать его содержимое. Возможно, я не совсем понимаю Ваших намеков.
Проблемы с кодировкой наблюдались у меня в случае, когда я делал так:
wget google.com/index.html
И далее использовал полученный файл, как документ.
Если же я самостоятельно напишу документ в текстовом редакторе по всем правилам указания кодировок — таких проблем не возникает.
Теперь усложним задачу:
Для начала заметим, что значение дескриптора socket и accept в программе:
sock = socket(...);//4
session = accept(sock, ...); // 5
Теперь запустим нашу программу как демон из другой програмы:
if(!fork()) execl("myprog", argv);
Наша программа успешно запустилась и ждет входящих сообщений, но не обрабатывает их (т.е. по-просту, не работатет).
И почему-то указанные выше sock и session на 1 меньше:
sock = socket(...);//3
session = accept(sock, ...); // 4
Что тут не так?
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Здравствуйте, Handler, Вы писали:
O>>Тут не хватает заголовка Content-Type c нужным charset-ом.
H>Вот я сейчас не понял — как и где его не хватает? В str он есть, а в заголовок его не надо писать.
У веб-сервера, который отдает HTML-страницу, есть два места для указания кодировки.
Первое, и главное место, — это заголовок HTTP-ответа Content-Type.
В нем указывается MIME-тип документа и его кодировка.
Например: "Content-Type: text/html; charset=Windows-1251".
Второе место находится внутри самого HTML — это атрибуты элемента <meta>.
Но браузер не обязан на них смотреть. По спецификации HTTP (RFC 2616, Chapter 3.4.1),
если кодировка не указывается в заголовке Content-Type, по умолчанию принимается ISO-8859-1,
и наплевать что там внутри <meta>.
H>что мне клиент прислал, то я и показал- все вопросы к веб-браузеру. Да и как, собственно, браузер может требовать кодировку? Его дело — запрашивать документ и отображать его содержимое. Возможно, я не совсем понимаю Ваших намеков.
Браузер может запрашивать не только кодировку, но и язык, способ компрессии, метод передачи и другие данные.
Например, если Вы зайдете на Google из Китая, увидите главную страницу с иероглифами.
Вопрос — как это достигается ? Отнюдь не по айпи. Когда браузер шлет запрос серверу, в этом запросе
обычно указываются некоторые "пожелания":
Accept: text/html — хочу получить такую веб-страницу,
Accept-Language: ru — чтоб контент был на русском,
Accept-Charset: Windows-1251 — и чтоб все это было в кодировке Windows-1251,
Accept-Encoding: x-gzip — пусть сервер в целях экономии трафика пожмет страницу GZip-ом.
Если сервер в состоянии удовлетворить такие пожелания, он вернет нужный контент.
Если нет, будет ответ 400 (Bad Request), 406 (Not Accepted), или что-то в этом роде.
Само собой, браузер, установленный на компьютере с китайской локализацией операционной системы,
или настроенный на такую локализацию, будет слать запросы с другими Accept-ами и получать от
сервера данные в других языках и кодировках.
В приведенном коде эта техника игнорируется, поэтому результаты не совпадают с ожиданиями.
H>Проблемы с кодировкой наблюдались у меня в случае, когда я делал так:
H>wget google.com/index.html H>И далее использовал полученный файл, как документ. H>Если же я самостоятельно напишу документ в текстовом редакторе по всем правилам указания кодировок — таких проблем не возникает.
Я пока вижу только одну проблему — HTTP-запросы и ответы игнорируют заголовки Accept-Charset и Content-Type.
H>Теперь усложним задачу: H>Для начала заметим, что значение дескриптора socket и accept в программе: H>sock = socket(...);//4 H>session = accept(sock, ...); // 5
H>Теперь запустим нашу программу как демон из другой програмы: H>if(!fork()) execl("myprog", argv);
H>Наша программа успешно запустилась и ждет входящих сообщений, но не обрабатывает их (т.е. по-просту, не работатет). H>И почему-то указанные выше sock и session на 1 меньше: H>sock = socket(...);//3 H>session = accept(sock, ...); // 4
H>Что тут не так?
Ну например, из-за того, что обе копии программы биндят сокет на один и тот же порт (8080).
H>Создать приложение демон-процесс, слушающий и обрабатывающий запросы к TCP порту основанные на HTTP, выдающий в результате обработки запроса HTML-контент взятый из базы данных mysql, выполняющий перекодирование выдаваемого контента в желаемую/затребованную кодировку, которая устанавливается либо в самом запросе, либо в настройках его инициализационных параметров.
Для перекодирования текстового содержимого нужно использовать сторонние библиотеки.
Например, iconv. Лично я предпочитаю библиотеку ICU.
Логика работы веб-сервера тогда будет примерно следующей:
Принимаем HTTP-запрос, вытаскиваем из заголовка "Accept-Charset" кодировку (или берем ее
из настроек нашего веб-сервера), затем добываем HTML-контент из базы данных, перегоняем
его в нужную кодировку, после чего формируем заголовки ответа, не забыв про Content-Type и
charset, и в полученном виде отдаем клиенту.