LINUX.ORG.RU

Boost asio для начинающих

 ,


0

2

Здравствуйте,

Начал попытку изучить основы boost asio и и сразу же появились вопросы :( Если есть возможность подскажите пожалуйста:

1)Я так и не могу понять, как работает функция read, то есть, как они понимает, что чтение пора завершать и передавать действие следующей строчке кода ? Единственно, что я смог заметить, это, если делать get http запрос в сторону сервера и указать Connection: close, то чтение read`ом происходит сразу и быстро, если же не указать Connection: close, то функция «чего то» ждет секунд 30 и только потом завершается. Из этого получаются еще вот такие вопросы: 2)Судя по всему функция read ждет отключения соединения со стороны сервера и только после этого считает, что все данные считаны, потому что у read_untill такой «проблемы» нет.

И иcходя из этого еще получаются вот такие вопросы: 3)Вообще по http 1.1, если я правильно понимаю, если не указать Connection: close, то сервер не должен закрывать соединение и должен его держать чуть ли не до второго пришествия, но в моем случае, соединение скорее всего закрывалось, хотя сервер и присылал «Connection: keep-alive», вопрос почему ? Или все таки это было не закрытие присоединения ?

4)И что такие вообще закрытие присоединения со стороны сервера , что это значит ? То есть, я создаю обьект boost socket, socket.open(), socket.conection() далее пишу в сокет, get запрос, пишу Connection: close, чтобы сервер закрыт соединение после того, как передаст всю инфу на мой get запрос, далее от сервера приходит так же Connection: close. Далее я проверю открыт ли мой сокет:

cout<< socket.is_open()<<endl;

И ответ: 1

то есть сокет открыт, что тогда такое Connection: close ??

5)Если в http 1.1 предусмотрен режим постоянного соединения, то, возвращаясь к самому первому вопросу, как работает read, как read понимает, или должен понимать, что все данные записаны и пора передавать команду следующей строчки кода ?

Как то вот такие вопросы получились, не судите строга пожалуйста :)

По boost.asio есть отличный цикл статей на хабре. И еще в документации по boost.asio куча примеров. И еще, то как работает boost.asio лучше рассматривать отдельно от того, как работает протокол http. На какое-то время забудь в принципе про http, и досконально разберись с boost.asio. И далее приведи пример кода с вызовом read (чтобы мы видели переданные параметры) (опять же без подмешивания http) и спроси, как она работает.

rumgot ★★★★★ ()

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

anonymous ()

Вам батенька надо не с asio разбираться а с сетевым и системным программированием. В частности нужно понимать как устроен tcp и каким образом планируется [а]синхронный ввод/вывод.

pon4ik ★★★★★ ()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от rumgot

Здравствуйте,

Спасибо, да, я эти переводы на habre читал и документацию на офф. сайте буста тоже.

Но все равно непонятно, как работает функция read в плане завершения операции чтения. Я использую вот такой код:

boost::asio::io_service io_service; tcp::resolver resolver(io_service); boost::system::error_code ec;

tcp::resolver::query query(URL, 80); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, ec);

boost::asio::ip::tcp::endpoint ep = *endpoint_iterator;

tcp::socket socket(io_service);

socket.open();

socket.connect(ep);

...boost::asio::write(socket, request);

boost::asio::streambuf response;

read(socket,response, transfer_all(), ec);

Optimus1 ()
Ответ на: комментарий от anonymous

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

Примеры для Boost Asio пишут очень умные люди, которые мастерски обходят в них сложные вопросы и косяки самого Boost Asio.

Чего стоит хотя бы бесконечный цикл в main, обрабатывающий io_service. Ибо процесс корректного завершения в Boost Asio очень мутный, и имеет целую гору подводных камней. По этому они решили просто забить на него.

dnf83 ()
Ответ на: комментарий от dnf83

Чего стоит хотя бы бесконечный цикл в main, обрабатывающий io_service

Ну да, покажи мне хоть одно не пакетное приложение где в main нет бесконечного цикла в или ожидания завершения такого в другом потоке…

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

Целый stop нужно вызвать и понимать хоть немного чего делаешь то вообще;)

pon4ik ★★★★★ ()

1. read читает столько сколько задано, в доках же написано. read_some читает сколько есть.

3. Без кода неясно что не так

4. Сервер твой сокет закрыть не может.

Ты бы сначала написал это без бустов, на юниксовых вызовах. Проще понять, больше описаний и примеров.

не судите строга

строга

Нет, судить тебя нужно еще как строго.

anonymous ()
Ответ на: комментарий от anonymous
boost::asio::io_service io_service; tcp::resolver resolver(io_service); boost::system::error_code ec;

tcp::resolver::query query(URL, 80); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, ec);

boost::asio::ip::tcp::endpoint ep = *endpoint_iterator;

tcp::socket socket(io_service);

socket.open();

socket.connect(ep);

...boost::asio::write(socket, request);

boost::asio::streambuf response;

read(socket,response, transfer_all(), ec);
Optimus1 ()
Ответ на: комментарий от anonymous
1. read читает столько сколько задано, в доках же написано. read_some читает сколько есть.

Задано кем и где ? В доках не видел такого описания.

Optimus1 ()
Ответ на: комментарий от dnf83

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

anonymous ()
Ответ на: комментарий от Optimus1

Задано тобой, размер буфера. Не видел?

Сколько тебе приходит? Видимо, меньше.

По этому фрагменту непонятно где проблема. Почему думаешь что соединение закрывается? «Или все таки это было не закрытие присоединения» - что «это»?

Будь не так загадочен, пожалуйста. И используй тэг

 для кода.

anonymous ()
Ответ на: комментарий от anonymous

Чуть выше код, который по сути из примера с сайта boost. Там для функции read ничего не задается, и она работает. Да и не всегда заранее можно знать сколько байт вообще нужно считать.

Optimus1 ()
Ответ на: комментарий от Optimus1

так стоп, мы говорим про документацию асио
показывайте где и что вы в _ней_ прочитали(в документации) о том что ничего не задается

anonymous ()
Ответ на: комментарий от dnf83

Лол. Не ну если для кого-то сиё ракетная наука, то может и ему немного теОрии подучить. Про планировщики там, циклы обработки событий и прочую ненужную лабуду. Глядишь и хелпы по api ко всему этому говну перестанут напоминать китайскую грамоту, и хитрожопость разработчиков того же буста куда то пропадёт.

pon4ik ★★★★★ ()
Ответ на: комментарий от anonymous

Ты бы сначала написал это без бустов, на юниксовых вызовах. Проще понять, больше описаний и примеров.

Удваиваю. Потом на select/poll переписать, потом на epoll, потом вроде как и те ссаные 70 строчек в io_service::run начнут наполняться смыслом.

pon4ik ★★★★★ ()
Ответ на: комментарий от Optimus1

не всегда заранее можно знать сколько байт вообще нужно считать

Так то - в том числе и для этого, и существуют протоколы прикладного уровня.

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

asio это всего лишь обёртка для системных вызовов, довольно тонкая, старается мимикрировать под unix стиль, но при этом инкапсулирует и виндовый iocp. Но у тебя пока всё синхронно. Так что слушай анона - разберись сначала как оно работает, а потом уже в шоткаты лезь.

pon4ik ★★★★★ ()
Ответ на: комментарий от pon4ik

Лол. Не ну если для кого-то сиё ракетная наука,

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

pathfinder ★★★★ ()
Ответ на: комментарий от pathfinder

асио писал марсианином на неизвестном никому языке ?
если асио не понятен, значит нужно начать с основ языка С++ а не с сетевого программирования
да еще и на асио, не, я понимаю что большинство школьников хотят сразу в синьоры на зп в $5к
но это как раз и есть порогом вхождения которым можно фильтровать школоту

anonymous ()
Ответ на: комментарий от pathfinder

Хз я раньше переживал за шаблоны, но потом почитал Джосатиса пару раз и как-то попроще стало, spirit и phoenix конечно сложненько читаются, но вот в asio прям магии магии я не наблюдал.

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

pon4ik ★★★★★ ()

Во, я придумал. Возьми python, возьми SO, и потыкай сокеты там. Там даже select есть из коробки. Лень книжки читать, хочется практики - socat + wireshark в зубы и SOD во все поля.

pon4ik ★★★★★ ()
Ответ на: комментарий от pon4ik

но вот в asio прям магии магии я не наблюдал

Давай рассмотрим операцию чтения.

Вот функция чтения из стандартной библиотеки:

ssize_t read(int fd, void *buf, size_t count);
Тут все просто и понятно. Прочитав man можно быстро понять, как пользоваться read().

А вот пример из asio:

template<
    typename SyncReadStream,
    typename MutableBufferSequence>
std::size_t read(
    SyncReadStream & s,
    const MutableBufferSequence & buffers,
    typename enable_if< is_mutable_buffer_sequence< MutableBufferSequence >::value >::type *  = 0);

Если мы хотим быстро глянуть в API reference и начать писать код, то со во вторым случаем будут проблемы. Надо разбираться с этим MutableBufferSequence, enable_if и прочим. Что это такое? Что можно? Чего нельзя? Нужно глубоко погрузиться в изучение библиотеки. Поэтому и высокий начальный порог вхождения.

Да, и если в код не собирается, то компилятор порадует полотном трудночитаемого сообщения об ошибке.

pathfinder ★★★★ ()
Последнее исправление: pathfinder (всего исправлений: 1)
Ответ на: комментарий от pathfinder

«апи» асио не читается по «ман рид»
необходимы знания работы сети + сетевого апи + С++ + понимая ивен драйвен подхода
да и вообще давайте дадим совершенно тупому и далекому человеку от программирования начать писать сетевой код да еще и после man read как вы намекаете
значит минимальный порог для этого обычного read он тоже есть
но для асио он намного выше

anonymous ()
Ответ на: комментарий от pathfinder

Я не спорю что интерфейс сложнее чем в C. Однако, о5 же, кому то придётся погружаться и в то, что значит void*.

Второй момент - в доке никаких enable_if нету, это просто средство реализации полиморфизма. Условия завершения функции тоже чётко показаны. По месту дан пример эквивалентный для C.

pon4ik ★★★★★ ()
Ответ на: комментарий от pathfinder

а какая последняя версия асио на текущий момент ?
вывод - вы троль

anonymous ()
Ответ на: комментарий от pathfinder

Ну как бы я взял с сайта буста хоть и не для самой актуальной версии. В любом случае - стран тот плюсовый погромист который не вкурил enable_if. Я минуты 2 вдуплял что именно тебе не понравилось в том коде :)

pon4ik ★★★★★ ()
Ответ на: комментарий от pon4ik

Немного офтопа: как у asio с производительностью/расходом памяти? Сам на тяжелых задачах его не использовал, может у тебя был опыт

anonymous ()
Ответ на: комментарий от anonymous

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

anonymous ()
Ответ на: комментарий от anonymous

т.е. я сейчас быстренько что то заговнокодю - с асио не пройдет

Фи. Берешь пример и модифицируешь под себя. Я даже видет такие http-серваки в проде(из примеров asio, еще до появления boost beast).

anonymous ()
Ответ на: комментарий от anonymous

ok. Насчет «быстренько» - кажется asio гораздо лучше в этом плане, чем native api(с другими интерфейсами, например libevent, я не работал, так что возможно неправ)

anonymous ()
Ответ на: комментарий от anonymous

да да знаем таких умников, потом они же бегают по форумам и спрашивают отчего и почему у них все падает
и как это дебажить

anonymous ()
Ответ на: комментарий от anonymous

асио это настройка над нейтив api
но и за executors / coroutines она выигрывает у libevent итд

anonymous ()
Ответ на: комментарий от anonymous

Из того что я видел - сравнительно с написанием ручками. Особенно если не смешивать i/o и всякие таймеры в одном цикле. Но народ всё равно в итоге выкидывает когда надо начинать выжимать всё-всё.

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

Из того что в проде с бустом жило - имело требования 40us передачу между системами по udp и немного бизнес логики в сети с лэйтенси для голого udp 4-6us. Правда из asio там разве что udp сокеты исползовались, очереди все свои были. Узким местом там буст ожидаемо не был.

pon4ik ★★★★★ ()
Ответ на: комментарий от anonymous

Сервер твой сокет закрыть не может.

Сокет закрыть не может, а защатдаунить соединения так чтобы recv/read возвращали 0 очень даже может. И будет у вас потом чтение из закрытого соединения через открытый сокет

Nastishka ★★★★★ ()
Последнее исправление: Nastishka (всего исправлений: 1)
Ответ на: комментарий от Nastishka

Если я правильно понял, то такого чтения не будет, так как будет ошибка конца потока eof.

Optimus1 ()

Здравствуйте,

Подскажите пожалуйста, вот делаю async_resolve на boost asio, все работает, отправляется запрос на резолв, далее срабатывает handler. Но вопрос, как результат хендлера выаести из main ? К примеру, как вывести результат хендлера значение tcp::resolver::iterator endpoint_iterator в main ?

void handler_resolve(const boost::system::error_code& error, tcp::resolver::iterator endpoint_iterator) { if (!error) { std::cout << «Резолв успешен» << endl;

tcp::endpoint endo_pointo = *endpoint_iterator;

cout << endo_pointo.address().to_string() << endl; } else { std::cout << «Ошибка: » << error.message() << endl;; } }

int main() { string URL_name="http://www.games.ru"

boost::asio::io_service io_services;

tcp::resolver resolvers(io_services); boost::system::error_code ec;

tcp::resolver::query query(URL_name, «80»); resolvers.async_resolve(query, handler_resolve); } io_services.run(); }

Optimus1 ()
Ответ на: комментарий от Optimus1

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

anonymous ()
Ответ на: комментарий от anonymous

Спасибо за очевидность))))) Я и сам понимаю, что не получается. У Вас ведь тоже не получается мне подсказать. Намекните :)

Optimus1 ()
Ответ на: комментарий от Nastishka

Сокет закрыть не может, а защатдаунить соединения так чтобы recv/read возвращали 0 очень даже может

Само собой, но ТС проверяет is_open и удивляется.

anonymous ()
Ответ на: комментарий от anonymous

Прошу прощения, так вставляется код, или может я его все таки не правильно вставил. Но, вопрос такой, в main выполняктся функция async_resolve, у функции есть handler_resolvе, который возвращает значения: -const boost::system::error_code& error -tcp::resolver::iterator endpoint_iterator

Вопрос, как эти значения получить ?

Optimus1 ()
Ответ на: комментарий от Optimus1

Да, ты неправильно вставляешь. Смотри описание разметки.

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

Если хочешь простое последовательное исполнение, хоть целиком в main, - бери синхронные функции.

anonymous ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.