Asio 注意事项 – DoubleLi

本文清单了 Asio 各式各样的值当睬的各种细节。

另见:鉴于 Asio 的 C++ 电网络顺序

No Deprecated

包体中 Asio 头文档过去的,界说宏 BOOST_ASIO_NO_DEPRECATED,这是在波湾阴谋时。,Asio 它将排除老一套的喷嘴。。

譬如,最新的。 Boost 1.66 中,io_service 早已改名为 io_context,假使缺席 BOOST_ASIO_NO_DEPRECATED,它依然可以被运用。io_service 的,固然那可是io_context 的本人 typedef

BOOST_ASIO_NO_DEPRECATED您可以抵押运用最新版本。 API。长久的视图,迅速地保持的约定遗传密码。。不管,这些修正案是 Asio 规范书屋序曲。

#define BOOST_ASIO_NO_DEPRECATED
#include "boost/asio/"
#include "boost/asio/"
...

_WIN32_WINNT Warning

在 Windows 平台,波湾阴谋时,你会偶遇_WIN32_WINNT 的正告。
在某种程度上,这是 Asio 本身的成绩。
它本应包罗在某处。
不应容许用户自动地界说平台的版本。。

假使你运用它 CMake,它可以由上面的宏感到。_WIN32_WINNT
(详见):https://stackoverflow.com/a/4…

if (Win32)
    macro(get_WIN32_WINNT 版本)
        if (CMAKE_SYSTEM_VERSION)
            集中(VER) ${CMAKE_SYSTEM_VERSION})
            字母串(权威的声调) MATCH "^([0-9]+).([0-9])" ver ${ver})
            字母串(权威的声调) MATCH "^([0-9]+)" verMajor ${ver})
            

包罗头文档放量少。

放量不要包罗大的和满的。boost/
大约做。,帮忙本人读熟哪个类出生于哪个考虑到的头。,并撤销不必要的的头文档。。

在实践工程中,在你本人的本人头文档中,它是复杂而粗糙的。boost/这不侵吞。;自然,包括在源文档中。boost/这是可以同意的。,归根结蒂,实践一件商品松劲更多的事实。,很难弄清楚每个界说是从哪里来的。。

Handler 署名成绩

固然几乎 Handler 的署名,文档中有阐明。,但立即的使适应源约定遗传密码。,更手边的,也更正规的。

以 () 为例,在 IDE 里使适应到 async_wait() 的界说,约定遗传密码(分离)如次:

template <typename WaitHandler>
  BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
      void (Booo::零碎:Error约定遗传密码)
  async_wait(BOOST_ASIO_MOVE_ARG(WaitHandler) 处置顺序)
  {
    ...

经过宏BOOST_ASIO_INITFN_RESULT_TYPEWaitHandler署名显而易见。。

Handler 的 error_code 决定因素其中的哪一个被援用?

说起来,最前部版本本应是const Boo::零碎:Error约定遗传密码,这执意文档和约定遗传密码正文中所写的愿意的。,据估计,缺席时期补充。。
后面说 Handler 署名时期,早已通知 BOOST_ASIO_INITFN_RESULT_TYPE大约宏的指出,两面派的 Asio 源码,error_code说起来,它早已被珍视了。。

出人意料的的事实是,公平的你是 Handler 传 error_code 为援用,波湾阴谋和运转缺席成绩。。

void Print(const Boo::零碎:Error约定遗传密码 欧共体) {
  std::cout << "Hello, world!" << std::endl;
}

int main() {
  boost::asio::io_context ioc;
  boost::asio::deadline_timer timer(国际奥林匹克委员会), Posix:时期:秒3));

  捣碎)

  ();
  return 0;
}

我查明了,当 Handler 是本人分子作用。,就危笃。以下是以下愿意的 timer 的举例,假使Print 的 error_code更反而援用,它不克不及波湾阴谋。。

class Printer {
public:
  ...

  void Start() {
    (STD::Band(和捣碎机::捣碎), this, STD:占位符::1)
  }

private:
  

大约成绩习惯于。,害苦了我,真参加隐晦。!它也被以为是 Boost 构成坑的得名次。。

Bind 占位符

让与 bind 时,占位符(占位符)被运用。,说起来,以下四种特征是可以同意的。:

Boo::绑定(捣碎), boost::asio::placeholders::error, &timer, 伯爵)
Boo::绑定(捣碎), 占位符::, &timer, 伯爵);
Boo::绑定(捣碎), _1, &timer, 伯爵);
STD::绑定(捣碎), STD:占位符::, &timer, 伯爵);

第一种,占位符是 Boost Asio 界说的。
以第二位种,占位符是 Boost Bind 界说的。
第三种,异样的以第二位种,认为某作品出自某人之手可行的,是由于 boost/外面有简而言之。using namespace 占位符:

四的种,STL Bind,相似地 Boost Bind,可是缺席发表宣言。using namespace STD:占位符

著作的四种方法,约定两个或四的。至若运用 Boost Bind 寂静 STL Bind,这不许的要紧。。
以及,数字占位符共享 9 个,_1 - _9

Endpoint 这是个词。

不要写 "end point"。

Server 也可以用 Resolver

TCP Server 的 acceptor 这通常是确认的。:

TCP:受主(IOL环境), TCP:晚期的(TCP::V4), 接口)

也执意说,约定 protocol (tcp::v4()) 和 port 就行了。

只是,Asio 的 http 大约举例,它的确运用了它 resolver,鉴于 IP 地址 resolve 出 endpoint:

  tcp::resolver resolver(io_context_);

  TCP::Deffiver::ReulsType典型 endpoints = (地址), 接口)

  TCP:晚期的 endpoint = *();

  (());
  (TCP::同意者:复用地址真的)
  (晚期的)
  ();

  (...);

http 这执意为什么写大约举例的发生因果关系。,首要是设定初值。acceptor_ 时,还得不到 endpoint,要不然可以立即的用以下是以下愿意的确认作用:

basic_socket_acceptor(boost::asio::io_context& io_context,
      const endpoint_type& endpoint, bool reuse_addr = 真的)

确认作用正文表现它相当于上面的约定遗传密码。:

basic_socket_acceptor acceptor(io_context);
(());
if (reuse_addr)
  (socket_base::reuse_address(真的)
(晚期的)
(listen_backlog);

以下是特色的。address 对应的 endpoints 导致(装出) port 都是8080):

  • "localhost": [::1]:8080, v6; []:8080, v4
  • "": :8080, v4
  • "0::0": [::]:8080, v6
  • 机具的确凿性 IP 地址 (譬如), IPv4 ""): :8080, v4。这时候,本机 client 无法经过 "localhost" 连接到大约 server,经过详细 IP 地址是可以的。。
  • 本人考虑到的非土著的地址 (譬如), IPv4 ""): exception: bind: The requested address is not valid in its context

Move Acceptable Handler

运用  时,查明了 Move Acceptable Handler。

复杂来说,async_accept同意两种 AcceptHandler,立即的检查源约定遗传密码:

template <typename MoveAcceptHandler>
  BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
      void (Booo::零碎:Error约定遗传密码), typename 一致::套接字
  async_accept(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) 处置顺序)
template <typename Protocol1, typename AcceptHandler>
  BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
      void (Booo::零碎:Error约定遗传密码)
  async_accept(basic_socket& peer,
      BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
      typename enable_if::value>::type* = 0)

第本人是 Move Acceptable Handler,它的以第二位个决定因素是新的。 accept 的 socket。
以第二位个是普通的。 Handler,它的第本人决定因素是预先付款确认的。 socket。

向 Move Acceptable Handler,用 bind 行不通。譬如,预先布置本人预先布置的:

void Server::HandleAccept(Booo::零碎:Error约定遗传密码) ec,
                          boost::asio::ip::tcp::socket 插座) {
}

在 VS 2015 在(伴奏下) C++14),STD::绑定可以波湾阴谋,Boost::绑定 则不灵。

在 VS 2013 下,STD::绑定 和 Boost::绑定 都不灵。

意见是,向 Move Acceptable Handler,不要用 bind,立即的用 lambda 声调:

void DoAccept() {
  (
    [this](Booo::零碎:Error约定遗传密码) ec, boost::asio::ip::tcp::socket 插座) {