Документация Boost.Asio действительно проделывает фантастическую работу, объясняя две концепции.Как упомянул Ральф, Крис также имеет отличный блог, описывающий асинхронные концепции.Пример парковочного счетчика , объясняющий, как работают тайм-ауты, особенно интересен, как пример bind, показанный .
Сначала рассмотрим операцию синхронного соединения:
Поток управления здесь довольно прост, ваша программа вызывает некоторый API (1) для подключения сокета.API использует сервис ввода-вывода (2) для выполнения операции в операционной системе (3).После завершения этой операции (4 и 5) управление сразу же возвращается к вашей программе (6) с некоторым указанием на успех или неудачу.
Аналогичная асинхронная операция имеет совершенно другой поток управления:
Здесь ваше приложение инициирует операцию (1), используя ту же службу ввода-вывода (2), но поток управления инвертируется.Завершение операции приводит к тому, что служба ввода-вывода уведомляет вашу программу через обработчик завершения.Время между шагом 3 и завершением операции полностью содержалось в операции соединения для синхронного случая.
Вы можете видеть, что синхронный случай, естественно, легче понять большинству программистов, поскольку он представляет традиционный поток управленияпарадигм.Инверсный поток управления, используемый асинхронными операциями, трудно понять, он часто вынуждает вашу программу разделять операции на методы start
и handle
, в которых логика смещается.Однако, как только вы поймете основы этого потока управления, вы поймете, насколько мощна эта концепция.Некоторые из преимуществ асинхронного программирования:
Отсоединяет потоки от параллелизма.Возьмите длительную операцию, для синхронного случая вы часто создаете отдельный поток для обработки этой операции, чтобы не дать GUI приложения перестать отвечать на запросы.Эта концепция прекрасно работает в небольшом масштабе, но быстро разваливается при небольшом количестве потоков.
Повышение производительности.Дизайн потока на соединение просто не масштабируется.См. Проблему C10K .
Композиция (или Цепочка).Операции более высокого уровня могут состоять из нескольких обработчиков завершения.Рассмотрите возможность передачи изображения JPEG, протокол может диктовать, что первые 40 байтов включают заголовок, описывающий размер изображения, форму, возможно, некоторую другую информацию.Первый обработчик завершения для отправки этого заголовка может инициировать вторую операцию для отправки данных изображения.Операция более высокого уровня sendImage()
не должна знать или заботиться о цепочке методов, используемых для осуществления передачи данных.
Время ожидания и возможность отмены.Существуют специфичные для платформы способы тайм-аута длительной работы (например: SO_RCVTIMEO
и SO_SNDTIMEO
).Использование асинхронных операций позволяет использовать deadline_timer
для отмены длительных операций на всех поддерживаемых платформах.
Конечно, в обеих операциях всегда существует риск того, чтоПри некоторых обстоятельствах поток программы останавливается на неопределенный срок - здесь используются таймеры, но я хотел бы узнать некоторые более авторитетные мнения по этому вопросу.
Мой личный опыт использования Asio связан с аспектом масштабируемости.Написание программного обеспечения для суперкомпьютеров требует значительных усилий при работе с ограниченными ресурсами, такими как память, потоки, сокеты и т. Д. Использование потока на соединение для ~ 2 миллионов одновременных операций является мертвым проектомпо прибытии.