asio支持TCP、UDP、ICMP等通信协议,它在名字空间boost::asio::ip里提供了大量的网络通信方面的函数和类,很好的封装了Socket API
TCP
- 类ip::tcp是asio网络通信(TCP)部分主要的类,表示TCP协议。
- 它本身并没有太大功能,而是定义了很多用于TCP通信的typedef类型,用来协作完成网络通信。它更像是一个名字空间
- 这些typedef包括端点类endpoint、套接字类socket、接收器acceptor、解析器resolver、流类iostream等
- 需引入头文件: < boost/asio/ip/tcp.hpp>
类摘要
示例
address
IP地址独立于TCP/UDP等通信协议,asio使用类ip::address来表示IP地址,可以同时支持IPv4、IPv6两种类型
类摘要
- from_string():从字符串产生IP地址
- to_string():将IP地址转换成字符串
示例
IP地址分为IPv4和IPv6两种,在Boost.Asio中分别由ip::address_v4和ip::address_v6表示,并提供了ip::address作为版本无关的IP地址表示。
#include <iostream>
#include <boost/asio.hpp>
using namespace boost::asio;
int main() {
// ip::address:from_string(str):这个函数根据一个IPv4地址(用.隔开的)或者一个IPv6地址(十六进制表示)创建一个地址。
ip::address addr = ip::address::from_string("192.168.135.1");
assert(addr.is_v4());
std::cout << "addr.is_v4():\t" << addr.is_v4() << std::endl;
std::cout << "addr.to_string():\t" << addr.to_string() << std::endl;
addr = addr.from_string("ABCD:EF01:2345:6789:ABCD:EF01:2345:6789");
assert(addr.is_v6());
std::cout << "addr.to_string():\t" << addr.to_string() << std::endl;
getchar();
return 0;
}
endpoint
有了IP地址,再加上端口号就构成了一个socket端点,在asio库中用ip::tcp::endpoint来表示
类摘要
示例
socket
socket类是TCP通信的基本类,它是basic_stream_socket的TCP协议特化
类摘要
- send()/receive()与write_some()/read_some()功能完全一致,内部都是调用系统函数sendmsg()/recvmsg()
- socket读写函数的参数都是buffer类型,可以用buffer()函数包装各种容器适配,区别在于send()/write_some()的参数是一个可读buffer,而receive()/read_some()要求是可写buffer
- async_xxx()可以使用两种形式的handler
acceptor
acceptor类对应Socket API的accept功能,它用于服务端,在指定的端口处接受连接,必须配合socket类才能完成通信。
acceptor是basic_socket_acceptor的TCP协议特化:
resolver
resolver类对应Socket API的getaddrinfo()系列函数,用于解析网址获得可用的IP地址(使用应用中一般只有一个域名),解析得到的IP地址可以使用的socket对象连接
类摘要
resolver是basic_resovler的TCP协议特化
示例
协程yield_context
协程是泛化的例程:
- 例程只有一个入口和多个出口。比如说函数,从最开始的函数入口开始,可以在某个时刻用return泛话,例程就结束了
- 协程有多个入口多个出口,从最开始的入口进入之后可以随时用yield调用返回,之后再调用协程就会从刚才返回的地方继续执行
boost中使用协程需要头文件< boost/asio/spawn.hpp>,并链接libboost_context.a、libboost_coroutine.a、libboost_thread.a
类摘要
asio协程主要类是yield_context,它是basic_yeild_context的typedef
- yield_context的接口很简单,它保存了协程的运行环境,交替执行主协程和从协程,达到异步的目的。
- operator[]用于外部获取发生的错误码,如果不适用operator[]则会抛出system_error异常来报告错误
- yield_context可以替代handler,async_xxx()函数就不需要写回调函数了,而是使用yield_context对象。async_xxx()调用后会自动交出控制权,执行其他的协程,直到异步操作完成时才会返回继续执行之后的动作
通常我们并不直接创建yield_context对象,而是使用spawn()。它产生yield_context_对象,再传递给使用yield_context的函数:
实例
这里在一个for循环里循环监听端口,但是它是在spawn()里利用协程实现的,接收连接和发送数据使用的是异步的async_accept和async_write_some,这样在每个异步调用处并不会阻塞,而是转入其他的协程。
流操作
对于TCP通信,asio库提供了一个ip::tcp::iostream类来简化socket通信。
客户端
服务端