| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > Почему не нужно использовать BSD-sockets?! |
| Автор: boostcoder 16.8.2011, 23:01 | ||||||||
| не понимаю я резона возиться с "этим"(BSD-sockets)! и не понимаю, что заставляет других использовать "это"! 1) отсутствие с++ компилятора? - это вряд ли, 2) не знание английского на столько, что даже доку по какому-то фреймворку/библиотеке(POCO, boost.asio, Qt) прочесть невозможно? - тоже маловероятно. 3) не знание с++? - тоже маловероятно. так в чем же причина?! - возможно в том, что многие даже не задумываются о том что существуют альтернативы? - а вот это возможно! а альтернативы есть, уверяю! и одна из них зовется http://www.boost.org/doc/libs/1_47_0/libs/asio/index.html. фух... высказался... итак. что же вам даст asio? 1. абстрагирование от платформы/ОС. 2. большое кол-во поддерживаемых платформ/ОС:
вы только вдумайтесь в каждый из перечисленных пунктов: 3.1. custom_memory_allocation - позволяет вам использовать собственный аллокатор для повышения скорости запросов на выделение памяти, и одновременно, полностью избежать фрагментации памяти! задумайтесь: boost::bind(который вы будите использовать почти везде при использовании asio) при создании функционального объекта выполняет new, а при разрушении - delete. а добавьте к этому аллоцирование буферов для операций чтения/записи, и это уже не мелочь! это здоровый кусок процессорного времени, тратится на не очевидные на первый взгляд действия. 3.2. invocation_strategy - при использовании custom_memory_allocation, позволяет производить вызов функциональных объектов, уже созданных ранее, и лежащих в аллокаторе! в добавок, invocation_strategy, при использовании вашим кодом нескольких рабочих потоков, полностью избавляет вас от необходимости разграничения доступа к общим ресурсам! т.е. никаких мьютексов! 4. очень удобную модель основанную на патернах http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/overview/core/basics.html и http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/overview/core/async.html. одумайтесь! пожалуйста, не пишите больше "такой" код. спасибо. зы даже не думал кого-то обидеть/задеть/оскорбить. зызы дописывать примеры буду в топик. следите. 1. Основы 1.1. http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/io_service.html: Основа любой программы использующей asio - io_service. Это означает, что Вы не можете создать объект сокета/аксептора не имея объекта io_service`а.
http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/io_service/run.html Если Вы используете только блокирующие операции, такие как http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/basic_socket_acceptor/accept.html или http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/basic_stream_socket/receive.html/http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/basic_stream_socket/send.html/http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/read.html/http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/write.html, то Вам вовсе не нужно вызывать io_service::run(). Иначе, читаем далее... Способы и правила вызова io_service::run() Бессмысленно вызывать io_service::run() раньше чем Вы создали хотя бы одну задачу. Т.е., задача - это результат создания любой асинхронной операции(не путать с _результат_выполнения_). Так, к примеру, http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/async_read.html создает задачу, которая будет выполняться до тех пор, пока не будет прочтено требуемое кол-во байт, или, пока не произойдет ошибка.
В этом примере, мы, при помощи async_read(), создаем _задачу_асинхронного_чтения_, и только после этого, вызываем io_service::run(). Иначе, если вызов io_service::run() и async_read() поменять местами, то наша программа завершится не успев начаться Если же у Вас высокопроизводительный сервер, то, возможно, Вы столкнетесь с тем, что Вам будет недостаточно одного рабочего потока. И Вы, как и любой порядочный программист, начнете изменять архитектуру для того, чтоб распределять задачи между несколькими рабочими потоками(трэды, очереди ,и т.д...). НЕ ДЕЛАЙТЕ ЭТОГО! В asio, это уже сделано за Вас. Немного изменяем предыдущий пример так:
Все! Теперь asio распределяет задачи между четырьмя рабочими потоками. Но в этом примере есть один не очевидный(на первый взгляд) подвох: когда закончатся задачи, io_service::run() вернет управление, и, как следствие, завершатся все рабочие потоки. И любая асинхронная операция более никогда не выполнится. Чтоб такого не произошло, изменяем пример следующим образом:
http://liveworkspace.org/code/167382d827125fa9ced4bf8905cca716 Теперь, вне зависимости от кол-ва задач, объект io_service`а будет продолжать работать и ожидать поступления новых задач. Для этого, мы создали объект типа http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/io_service__work.html. Почему объект io_service::work мы храним в смарт_поинтере? - потому что это дает нам возможность удалить его вызовом "work.reset()" для того чтоб завершить рабочие потоки и программу. 1.2. Буферы Скорее всего, вам это никогда не пригодится. Можете смело пропускать этот раздел Заглядывая в документацию по таким функциям/методам как http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/basic_stream_socket/receive.html/http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/basic_stream_socket/send.html/http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/read.html/http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/write.html, вы будите видеть типы параметров буферов, к примеру, http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/MutableBufferSequence.html, http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/ConstBufferSequence.html. Что же означают эти типы, и какие к ним требования? Все просто. Давайте рассмотрим требования к типу http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/MutableBufferSequence.html. В требованиях говорится про: value_type - который должен быть синонимом T. const_iterator - тип итератора, соответствующего требованиям bidirectional-итератора(http://cplusplus.com/reference/std/iterator/BidirectionalIterator/). const_iterator begin(); - метод, возвращающий итератор указывающий на первый элемент. const_iterator end(); - метод, возвращающий итератор указывающий на последний элемент. http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/ConstBufferSequence.html Имеет такие же требования, за исключением спецификаторов константности. 1.3. Время жизни буферов 1.4. Completion-handlers ...в процессе... |
| Автор: serghd 16.8.2011, 23:27 |
| Про custom_memory_allocation наслышан, да. В высоконагруженных системах самое оно. Пример invocation_strategy при использовании custom_memory_allocation если имеется, пожалуйста. Особенно интересен вызов функторов, лежащих в аллокаторе. |
| Автор: Sahab 16.8.2011, 23:33 |
| А Вы не думали сударь, что иногда бывает навязана стратегия реализации проекта. Например, использовать только бздишные сокеты? |
| Автор: boostcoder 16.8.2011, 23:35 |
это страшно. тем, кто находится в таком "положении" - строго настрого игнорить тему, дабы не разочаровываться ;) |
| Автор: serghd 24.8.2011, 20:28 | ||
http://liveworkspace.org/code/6baaa49522192ee72db32b0b3f9af140 Вопрос, наверное, ламерский, но тем не менее. Почему текст выводится один, а не 4 раза? Т.е. я понимаю, что после первого вывода ios должен возвратить управление. Но чтобы он работал дальше, мы используем work. Тогда в чём подвох? |
| Автор: boostcoder 25.8.2011, 14:57 |
| async_read() создает одну задачу. и выполняется одна задача. ты ведь не задачу создаешь четыре раза, а рабочие потоки. |
| Автор: serghd 25.8.2011, 18:19 |
| просто думал, что каждый поток вызывает свой async_read() (т.е. все они используют при этом один и тот же ios). Но если нет, значит нет) |
| Автор: Леопольд 9.9.2011, 13:20 | ||
|
| Автор: boostcoder 9.9.2011, 13:23 |
обрабатываете его в том же потоке, и, в зависимости от типа исключения, либо продолжаете работать, либо валите приложение. Добавлено через 1 минуту и 53 секунды ибо при возникновении исключения в любом и элементов очереди io_service, из очереди будет выброшен только этот элемент. поэтому этот же io_service спокойно может продолжить работать. иначе вообще, ничего бы не могло в asio работать нормально, при таком раскладе |
| Автор: Леопольд 9.9.2011, 13:36 |
| Т.е. во всех хендлерах, где может быть исключение, нужны try/catch? |
| Автор: newbee 9.9.2011, 13:42 |
| А где можно посмотреть непредвзятое сравнение высоконагруженного многопользовательского сервера на этом азио и линуксовом сишном epoll? Можно с распределением на равное число потоков или процессов. Интересует скорость реакции и число обработанных запрросов в единицу времени. |
| Автор: boostcoder 9.9.2011, 13:50 | ||
нет. try-catch нужно только в точке вызова io_service::run() |
| Автор: boostcoder 9.9.2011, 14:42 |
asio в лине и использует epoll. |
| Автор: newbee 9.9.2011, 14:46 |
| Я в курсе. Мне интересно сравнение чистого еполла и того, что спрятан за тысячью фасадов и колбэков в азио. |
| Автор: Леопольд 9.9.2011, 16:36 |
| В принципе, так и сделал (если я правильно уловил мысль), завернул io_service::run() в функцию с блоком try/catch. Наверное, в примере лучше тоже так сделать... |
| Автор: boostcoder 10.9.2011, 02:01 | ||
а в доку не пытались заглянуть? ;) http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/reference/io_service.html#boost_asio.reference.io_service.effect_of_exceptions_thrown_from_handlers. так же, есть способ который при помощи маленькой хитрости, позволяет отличать исключения возникшие в самой библиотеке(к примеру, при обрыве соединения), от исключений возникающих в пользовательских хэндлерах. но об этом в соответствующей главе. будет глава посвященная обработке ошибок/исключений. |
| Автор: Lazin 19.11.2011, 14:28 |
| Это глупое фанбойство! ACE как минимум ничем не хуже, а может даже лучше чем asio. А boost это же вообще ужас. |
| Автор: Олег2005 19.11.2011, 16:34 |
| Модератор: Для предотвращение холивара и оффтопа тема временно закрыта. Для дискуссий желающие могут открыть новую тему |