Boost Asio介绍
本文最后更新于:December 1, 2021 am
博文主要参考了Boost官网中关于Asio-Anatomy的文档,笔者对文档进行了翻译理解和整合。
题外话
关于NIO和ASIO的区别,可以简单地理解为
NIO通知Programmer事件就绪状态,数据从内核到用户空间的拷贝、以及后续对数据的操纵,需要Programmer手动进行,并且这个过程会阻塞线程。
ASIO中,发起请求前Programmer首先指定回调函数,内核负责准备数据和将数据拷贝到用户空间,并且调用指定的回调函数操纵数据。
总览
Asio可以同时支持同步I/O和异步I/O。 以对socket执行connect的同步和异步过程举例,说明Asio涉及了哪些类,以及它们如何工作。
核心概念介绍
boost::asio::io_conetxt io_context_obj被称作程序和操作系统I/O设备的连接点link。
Your program will have at least one io_context object. The io_context represents your program‘s link to the operating system‘s I/O services.
为了执行I/O操作,还需要申请一个I/O对象,比如一个TCP的Socket。我们在创建对象时将刚刚拿到的context对象传入。
boost::asio::ip::tcp::socket socket(io_context_obj);
同步过程

程序通过调用
socket对象的connect方法,初始化connect操作I/O对象
socket将请求转发forward到io_context上io_context发起系统调用OS完成过程,向
io_context返回结果如果返回了错误,
io_context会将错误包装成boost::system::error_code类型的数据,并被转发给I/O对象,在此处为socket。这种error_code可以和一个特定的值比较,比如可以作为boolean来测试,false说明没有发生错误。根据对I/O对象调用的函数不同,会有不同的结果;如果外部传入了接受ec的左值引用,那么函数调用会置ec为返回的结果;否则会抛出异常。
1
2
3boost::system::error_code ec;
socket.connect(server_endpoint, ec);
//这样不会抛异常
异步过程

异步调用时,我们会调用socket对象的不同函数。
socket.async_connect(server_endpoint, your_completion_handler);
其中第二个参数是一个函数签名,并且在此处(socket的connect中)应该有以下形式:
void your_completion_handler(const boost::system::error_code& ec);
- I/O 对象将请求转发到
io_context -
io_context示意操作系统应该发起一个异步的connect
一段时间过后(在同步调用的情况下,这一段时间应该包含在connect operation中
- 操作系统将结果放在一个队列中,以供
io_context取走 - 程序必须调用
io_context::run()(或者其它相似功能的成员函数)来取回connect的调用结果。当有未完成的异步操作时,调用io_context::run()会导致阻塞,因此一般情况下,当启动异步操作时,就会调用run()。 - 在
io_context::run()内部,io_context将connect的结果出队列dequeue,转换成error_code并且将之传入我们定义的your_completion_handler
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!