基于 Boost Asio 的 C++ 网络编程

您所在的位置:网站首页 asio与mme 基于 Boost Asio 的 C++ 网络编程

基于 Boost Asio 的 C++ 网络编程

2023-09-03 07:22| 来源: 网络整理| 查看: 265

基于 Boost Asio 的 C++ 网络编程

环境: Boost v1.66, VS 2013 & 2015

说明: 这篇教程形成于 Boost v1.62 时代,最近(2018/01)针对 v1.66 做了一次大的更新。 此外,在代码风格上,C++11 用得更多了。

概述

近期学习 Boost Asio,依葫芦画瓢,写了不少例子,对这个「轻量级」的网络库算是有了一定理解。但是秉着理论与实践结合的态度,决定写一篇教程,把脑子里一知半解的东西,试图说清楚。

Asio,即「异步 IO」(Asynchronous Input/Output),本是一个 独立的 C++ 网络程序库,似乎并不为人所知,后来因为被 Boost 相中,才声名鹊起。

从设计上来看,Asio 相似且重度依赖于 Boost,与 thread、bind、smart pointers 等结合时,体验顺滑。从使用上来看,依然是重组合而轻继承,一贯的 C++ 标准库风格。

什么是「异步 IO」?

简单来说,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知。

当然这种表述是不精确的,操作系统并没有直接提供这样的机制。以 Unix 为例,有五种 IO 模型可用:

阻塞 I/O 非阻塞 I/O I/O 多路复用(multiplexing)(select 和 poll) 信号驱动 I/O(SIGIO) 异步 I/O(POSIX aio_ 系列函数)

这五种模型的定义和比较,详见「Unix Network Programming, Volume 1: The Sockets Networking API」一书 6.2 节,或者可参考 这篇笔记。

Asio 封装的正是「I/O 多路复用」。具体一点,epoll 之于 Linux,kqueue 之于 Mac 和 BSD。epoll 和 kqueue 比 select 和 poll 更高效。当然在 Windows 上封装的则是 IOCP(完成端口)。

Asio 的「I/O 操作」,主要还是指「网络 IO」,比如 socket 读写。由于网络传输的特性,「网络 IO」相对比较费时,设计良好的服务器,不可能同步等待一个 IO 操作的结束,这太浪费 CPU 了。

对于普通的「文件 IO」,操作系统并没有提供“异步”读写机制,libuv 的做法是用线程模拟异步,为网络和文件提供了一致的接口。Asio 并没有这样做,它专注于网络。提供机制而不是策略,这很符合 C++ 哲学。

下面以示例,由浅到深,由简单到复杂,逐一介绍 Asio 的用法。 简单起见,头文件一律省略。

I/O Context

每个 Asio 程序都至少有一个 io_context 对象,它代表了操作系统的 I/O 服务(io_context 在 Boost 1.66 之前一直叫 io_service),把你的程序和这些服务链接起来。

下面这个程序空有 io_context 对象,却没有任何异步操作,所以它其实什么也没做,也没有任何输出。

1 2 3 4 5 int main() { boost::asio::io_context ioc; ioc.run(); return 0; }

io_context.run 是一个阻塞(blocking)调用,姑且把它想象成一个 loop(事件循环),直到所有异步操作完成后,loop 才结束,run 才返回。但是这个程序没有任何异步操作,所以 loop 直接就结束了。

Timer

有了 io_context 还不足以完成 I/O 操作,用户一般也不跟 io_context 直接交互。

根据 I/O 操作的不同,Asio 提供了不同的 I/O 对象,比如 timer(定时器),socket,等等。 Timer 是最简单的一种 I/O 对象,可以用来实现异步调用的超时机制,下面是最简单的用法:

1 2 3 4 5 6 7 8 9 10 11 void Print(boost::system::error_code ec) { std::cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3