boost asio的基本知识点

socket编程的基本步骤

socket编程的基本步骤罗列如下,只是列出一个基本流程,不涉及到错误处理,io操作的方式。万变不离其宗,asio中的最基本步骤也是如此,它对基本的socket api进行了封装。

UDP

服务端流程

  • 创建socket
  • bind ip地址和端口
  • io操作(recvfrom或sendto)

客户端流程

  • 创建socket
  • connect操作(可选)
  • io操作(recvfrom或sendto)

TCP

服务端

  • 创建socket
  • bind ip地址和端口
  • listen
  • accept
  • io操作

客户端

  • 创建socket
  • connect操作
  • io操作

asio的命名空间

asio的所有内容都包含在boost::asio命名空间或者其子命名空间内。

boost::asio:这是核心类和函数所在的地方。重要的类有io_service和streambuf。类似read, read_at, read_until方法,它们的异步方法,它们的写方法和异步写方法等自由函数也在这里。
boost::asio::ip:这是网络通信部分所在的地方。重要的类有address, endpoint, tcp, udp和icmp,重要的自由函数有connect和async_connect。要注意的是在boost::asio::ip::tcp::socket中间,socket只是boost::asio::ip::tcp类中间的一个typedef关键字。
boost::asio::error:这个命名空间包含了调用I/O例程时返回的错误码
boost::asio::ssl:包含了SSL处理类的命名空间
boost::asio::local:这个命名空间包含了POSIX特性的类
boost::asio::windows:这个命名空间包含了Windows特性的类

IP地址

对于IP地址的处理,Boost.Asio提供了ip::address , ip::address_v4和ip::address_v6类。 它们提供了相当多的函数。下面列出了最重要的几个:

ip::address(v4_or_v6_address):这个函数把一个v4或者v6的地址转换成ip::address
ip::address:from_string(str):这个函数根据一个IPv4地址(用.隔开的)或者一个IPv6地址(十六进制表示)创建一个地址。
ip::address::to_string() :这个函数返回这个地址的字符串。
ip::address_v4::broadcast([addr, mask]):这个函数创建了一个广播地址 ip::address_v4::any():这个函数返回一个能表示任意地址的地址。
ip::address_v4::loopback(), ip_address_v6::loopback():这个函数返回环路地址(为v4/v6协议)
ip::host_name():这个函数用string数据类型返回当前的主机名。

大多数情况会选择用ip::address::from_string:

ip::address addr = ip::address::from_string("127.0.0.1");

如果想通过一个主机名进行连接,下面的代码片段是无用的:

// 抛出异常
ip::address addr = ip::address::from_string("www.yahoo.com");

端点

端点是IP和Port对,对应于socket中的sockaddr_in(IPv4)等地址结构体,不同类型的socket有它自己的endpoint类,比如ip::tcp::endpoint、ip::udp::endpoint和ip::icmp::endpoint

如果想连接到本机的80端口,你可以这样做:

ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"), 80);

有三种方式来让你建立一个端点:

endpoint():这是默认构造函数,某些时候可以用来创建UDP/ICMP socket。
endpoint(protocol, port):自动选择本地IP,只需指定一个本地Port,通常用在服务端。
endpoint(addr, port):这个方法创建了一个远端的IP,Port对。

例子如下:

ip::tcp::endpoint ep1;
ip::tcp::endpoint ep2(ip::tcp::v4(), 80);
ip::tcp::endpoint ep3( ip::address::from_string("127.0.0.1), 80);

如果你想连接到一个主机(不是IP地址,通过域名),你需要这样做:

// 输出 "87.248.122.122"
io_service service;
ip::tcp::resolver resolver(service);
ip::tcp::resolver::query query("www.yahoo.com", "80");
ip::tcp::resolver::iterator iter = resolver.resolve( query);
ip::tcp::endpoint ep = *iter;
std::cout << ep.address().to_string() << std::endl;

你可以用你需要的socket类型来替换tcp。首先,为你想要查询的名字创建一个查询器,然后用resolve()函数解析它。如果成功,它至少会返回一个入口。你可以利用返回的迭代器,使用第一个入口或者遍历整个列表来拿到全部的入口。

给定一个端点,可以获得他的地址,端口和IP协议(v4或者v6):

std::cout << ep.address().to_string() << ":" << ep.port()
<< "/" << ep.protocol() << std::endl;

套接字

Boost.Asio有三种类型的套接字类:ip::tcp, ip::udp和ip::icmp

你可以把ip::tcp, ip::udp, ip::icmp类当作占位符;它们可以让你便捷地访问其他类/函数,如下所示:

ip::tcp::socket, ip::tcp::acceptor, ip::tcp::endpoint,ip::tcp::resolver, ip::tcp::iostream
ip::udp::socket, ip::udp::endpoint, ip::udp::resolver
ip::icmp::socket, ip::icmp::endpoint, ip::icmp::resolver

socket类创建一个相应的socket。而且总是在构造的时候传入io_service实例:

io_service service;
ip::udp::socket sock(service)
sock.set_option(ip::udp::socket::reuse_address(true));

每一个socket的名字都是一个typedef关键字

ip::tcp::socket = basic_stream_socket
ip::udp::socket = basic_datagram_socket
ip::icmp::socket = basic_raw_socket

socket成员方法

这些方法被分成了几组。并不是所有的方法都可以在各个类型的套接字里使用。注意所有的异步方法都立刻返回,而它们相对的同步实现需要操作完成之后才能返回。
socket类封装了socket编程中所有基本步骤,它有几个不同的构造函数。通过构造函数你可以单纯创建一个socket对象,也可以创建一个bind了指定地址和端口的socket对象。

读写函数

这些是在套接字上执行I/O操作的函数。

对于异步函数来说,回调处理函数的格式void handler(const boost::system::error_code& e, size_t bytes)都是一样的

async_receive(buffer, [flags,] handler):这个函数启动从套接字异步接收数据的操作。
async_read_some(buffer,handler):这个函数和async_receive(buffer, handler)功能一样。
async_receive_from(buffer, endpoint[, flags], handler):这个函数启动从一个指定端点异步接收数据的操作。
async_send(buffer [, flags], handler):这个函数启动了一个异步发送缓冲区数据的操作。
async_write_some(buffer, handler):这个函数和async_send(buffer, handler)功能一致。
async_send_to(buffer, endpoint, handler):这个函数启动了一个异步send缓冲区数据到指定端点的操作。
receive(buffer [, flags]):这个函数异步地从所给的缓冲区读取数据。在读完所有数据或者错误出现之前,这个函数都是阻塞的。
read_some(buffer):这个函数的功能和receive(buffer)是一致的。
receive_from(buffer, endpoint [, flags])*:这个函数异步地从一个指定的端点获取数据并写入到给定的缓冲区。在读完所有数据或者错误出现之前,这个函数都是阻塞的。
send(buffer [, flags]):这个函数同步地发送缓冲区的数据。在所有数据发送成功或者出现错误之前,这个函数都是阻塞的。
write_some(buffer):这个函数和send(buffer)的功能一致。
send_to(buffer, endpoint [, flags]):这个函数同步地把缓冲区数据发送到一个指定的端点。在所有数据发送成功或者出现错误之前,这个函数都是阻塞的。
available():这个函数返回有多少字节的数据可以无阻塞地进行同步读取。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mo4776

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值