Boost::Asio 第四章基本概念

本文详细介绍了Boost.Asio库中的核心组件和使用概念,包括重新命名空间如`boost::asio`、`boost::asio::ip`,以及IP地址处理、端点操作、套接字类型、并发执行、套接字控制等方面。通过实例展示了如何创建和操作套接字,以及如何进行同步和异步的读写操作,强调了在异步编程中保持对象活性的重要性。
摘要由CSDN通过智能技术生成
  1. Boost.Asio重新命名空间
    Boost.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例程时回到的deployed
    boost::asio::ssl:涵盖了SSL处置类的重新命名空间
    boost::asio::local:那个重新命名空间涵盖了POSIX特性的类
    boost::asio::windows:那个重新命名空间涵盖了Windows特性的类
  2. 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信息类别回到当前的Teredo。
大多数情况你会自由选择用ip::address::from_string:

ip::address addr = ip::address::from_string(“127.0.0.1”);

假如你想通过一种Teredo进行相连接,上面的编码片段是无用的:

// 扔出异常
ip::address addr = ip::address::from_string(“www.yahoo.com”);

  1. 东南侧 endpoint
    东南侧是采用某一路由器相连接到的一种门牌号。不同类别的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):那个形式通常用以建立能接受新相连接的服务器端socket。
endpoint(addr, 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;
1
4.套传输层
Boost.Asio有三种类别的套传输层类别:ip::tcp, ip::udp和ip::icmp。当然它也是可扩展的,你能建立自己的socket类,尽管这相当复杂。假如你自由选择这样做,参照一下boost/asio/ip/tcp.hpp, boost/asio/ip/udp.hpp和boost/asio/ip/icmp.hpp。它都是含有内部typedef关键字的超小类。

你能把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));
1
2
3
每一种socket的名字都是一种typedef关键字:

ip::tcp::socket = basic_stream_socket
ip::udp::socket = basic_datagram_socket
ip::icmp::socket = basic_raw_socket
5.并行deployed
大部份的并行表达式都有扔出异常或是回到deployed的重载,比如说上面的编码片段:

sync_func( arg1, arg2 … argN); // 扔出异常
boost::system::error_code ec;
sync_func( arg1 arg2, …, argN, ec); // 回到deployed

6.socket成员形式
那些形式被分成了几组。并不是大部份的形式都能在各个类别的套传输层里采用。那个部分的结尾将有一种列表来展示各个形式分别属于哪个socket类。

特别注意大部份的触发器形式都立刻回到,而它相对的并行同时实现须要操作形式顺利完成之后才能回到。

7.相连接相关的表达式
那些形式是用以相连接或半丁socket、断开socket字相连接以及查询相连接是活动还是非活动的:

assign(protocol,socket):那个表达式分配了一种原生植物的socket给那个socket示例。当处置老(旧)程序时会采用它(也就是说,原生植物socket已被建立了)
open(protocol):那个表达式用取值的IP协议(v4或是v6)打开一种socket。你主要在UDP/ICMP socket,或是服务器端socket上采用。
bind(endpoint):那个表达式绑定到一种门牌号
connect(endpoint):那个表达式用并行的形式相连接到一种门牌号
async_connect(endpoint):那个表达式用触发器的形式相连接到一种门牌号
is_open():假如套传输层已打开,那个表达式回到true
close():那个表达式用以关闭套传输层。初始化时那个套传输层上任何的触发器操作形式单厢被立刻关闭,同时回到error::operation_aborteddeployed。
shutdown(type_of_shutdown):那个表达式立刻使send或是receive操作形式失效,或是两者都失效。
cancel():那个表达式取消套传输层上大部份的触发器操作形式。那个套传输层上任何的触发器操作形式单厢立刻完结,接着回到error::operation_aborteddeployed。
范例如下表所示:

ip::tcp::endpoint ep( ip::address::from_string(“127.0.0.1”), 80); //建立东南侧
ip::tcp::socket sock(service); //建立套传输层示例
sock.open(ip::tcp::v4()); //用ipv4形式打开套传输层
sock.connect(ep); //并行相连接东南侧
sock.write_some(buffer(“GET /index.html\r\n”)); //那个表达式开启了一种触发器传送头文件信息的操作形式
char buff[1024];
sock.read_some(buffer(buff,1024));
sock.shutdown(ip::tcp::socket::shutdown_receive); //终止
sock.close(); //关闭

8.读取表达式
那些是在套传输层上继续执行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():那个表达式回到有多少字节的信息能无堵塞地进行并行加载。
稍后我将讨论头文件,让我先来了解一下标示。标示的默认值是0,也能是以下几种:

ip::socket_type::socket::message_peek:那个标示只监测并回到某一最新消息,但下一次读最新消息的初始化会重新加载那个最新消息。
ip::socket_type::socket::message_out_of_band:那个标示处置带外(OOB)信息,OOB信息是被标示为比正常信息更重要的信息。
ip::socket_type::socket::message_do_not_route:那个标示选定信息不采用路由表来传送。
ip::socket_type::socket::message_end_of_record:那个标示选定的信息标识了记录的完结。在Windows下不支持。
你最常用的可能是message_peek,采用形式请参照上面的编码片段:

char buff[1024];
sock.receive(buffer(buff), ip::tcp::socket::message_peek );
memset(buff,1024, 0);
// 重新加载以后已加载过的内容
sock.receive(buffer(buff) );

上面的是一些教你如何并行或触发器地从不同类别的套传输层上加载信息的范例:

在一种TCP套传输层上进行并行读取:
ip::tcp::endpoint ep(ip::address::from_string(“127.0.0.1”), 80);
ip::tcp::socket sock(service);
sock.connect(ep);
sock.write_some(buffer(“GET /index.html\r\n”));
std::cout << "bytes available " << sock.avaiable() << std::endl;
char buff[512];
size_t read = sock.read_some(buffer(buff));

在一种UDPTCP套传输层上进行并行读取:
ip::udp::socket sock(service);
sock.open(ip.udp::v4());
ip::udp::endpoint receiver_ep(“87.248.112.181”, 80);
sock.send_to(buffer(“testing\n”), receiver_ep);
char buff[512];
ip::udp::endpoint sender_ep;
sock.receive_from(buffer(buff), sender_ep);

特别注意:就像上述编码片段所展示的那样,采用receive_from从一种UDP套传输层加载信息时,你须要构造一种默认的东南侧

从一种

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值