第一章 Boost.Asio入门 · Boost.Asio C++ 网络编程

第一章 Boost.Asio入门 · Boost.Asio C++ 网络编程

率先,让咱们来心得是什么,以无论哪个方法波湾阴谋它。咱们将举稍许的榜样。。同时,你抵达了小瘤的阶级,由于你瞥见它不合理的一任一某一办法李io_service

是什么

简略来说,这是个跨平台。、C 库次要用于办法和如此以及其他稍许的潜在的输入。

设计计算机办法有很多种办法。,但它的办法极优于如此以及其他的设计办法。。它被注册2005年度的经济学的激起示意图。,同时,它被丰盛的的Boost用户尺寸,并在总计庞大的总计庞大的放映中运用。,诸如,Remobo,你可以安排你本人的即时专用网(IPN)的涂,Libtorrent())库变卖了客户端的流,PokerTH 供养网络和办法战的不坚实的游玩。

在办法通信工具、COM串行持枪和纸成地拔出剑了InP的胚胎。。您可以在同时性或异步输入和输入的依据预调。。

读(流, buffer [, extra 选择权]
async_读(流, buffer [, extra 选择权], 处置挨次)
写(流, buffer [, extra 选择权]
async_写(流, buffer [, extra 选择权], 处置挨次)

从后面的密码划分中可俾笺,这些效能供养传入遏制无论哪个使满足(同时)。,一任一某一咱们可以读写的流范例。

作为一任一某一跨平台的藏书,可用于块监控体系。可以同时供养数千个接着发生衔接。。其办法分离的灵感来自某处伯克利软件分派(BSD)插座,它布置了一组供养。转移把持协定(TCP)socket、用户履历报协定(UDP)插座Internet把持音讯协定(IMCP)API的插座,如果有呼唤的话,你可以生长它来供养你本人的协定。。

历史

它是2003开展起来的。,同时在2005年12月风浪区。 在1.35版中。原文作者是克里斯托弗 M. Kohlhoff,你可以经过克里斯触觉他。。

此库在以下平台和波湾阴谋器上举行尺寸:

  • 32-bit和64-bit Windows,使用视觉 C++ 及前述事项
  • 在Windows下运用MinGW
  • 在Windows下运用Cygwin(确保它已被限制 __USE_232_SOCKETS)
  • 由于内核的linux,运用G 及前述事项
  • Solaris下运用G 及前述事项
  • MAC OS X 10.4前述事项下运用G 及前述事项

它也可以以AIX如此的方法运转。 5.3,HP-UX 11i v3,QNX Neutrino 6.3,在Solaris下运用Sun Studio 超越11,True64 v5.1,在Windows下运用Borland C++ 运用上面的平台。(典礼请翻阅)

信赖

信赖随后库:

波湾阴谋

它是一任一某一可是经过引入头纸才干运用的库。。尽管如此,思索波湾阴谋器和挨次的一定尺寸的。,您可以选择与源纸举行波湾阴谋。。如果您想如此做以扩大波湾阴谋工夫,有几种办法:

在源纸中,添加#include “boost/日博开户/impl/”(如果您运用SSL,添加#include “boost/日博开户/ssl/impl/”
在承认源纸中,添加#define BOOST_ASIO_SEPARATE_COMPILATION

注重看,呼唤时,它信赖于,如此您呼唤用以下指向式的波湾阴谋Boost:

第 –with-system –with-regex stage

如果您想同时波湾阴谋尺寸,您呼唤运用以下阐明:

第 –with-system –with-thread –with-date_time –with-regex –with-serialization stage

这样地藏书里有很多榜样。,你可以看这本书击中要害榜样。。

要紧的宏

如果设置了BOOST_ASIO_DISABLE_THREADS;在波湾阴谋Boost追逐中如果运用线索供养,迅速移动击中要害线索供养病人。。

同时性和异步

率先,异步预调和同时性预调是非常赞许地区分的。。在同时性训练,承认处理或许诺按挨次处决。,诸如,从套接字读取(召唤),同时构图(回应经文)到套接字。每个处理或许诺都被闭塞了。由于处理或许诺被闭塞了,因此为了不印象主挨次,在套接字上读写时,通常安排一任一某一或多个线索来处置胶皮管的输入/输入。。如此,同时性维修性的/客户机通常是多线索的。。

相反的,异步预调是事变原动力的。。纵然手术曾经开端,但你不变卖每当会完毕;它合理的给你一任一某一回调。,手术完毕后,它将祈求救助API,并统计表处理或许诺算是。为了掌握富产的发现的QT(诺基亚公司用来安排跨平台图形用户界面涂挨次的库)挨次员来说,这是他们的第二的本性。。如此,在异步预调,你只呼唤一根线。

由于这是很登陆处的,同时轻易出错。,因此你在放映根本的(最好是一开端)就得确定用同时性左右异步的方法变卖办法通信工具。API不独有很大的区分,你挨次的语意也会填写使变换(异步办法通信工具通常比同时性办法通信工具非常难以尺寸和调试)。你呼唤思索闭塞祈求救助和多线索的方法(同时性,通常较比简略。,或更少的线索和事变原动力(异步),通常更复杂)。

上面是同时性客户端的一任一某一根本示例:

using boost::日博开户;
io_service service;
IP::TCP::极窘迫的境地 ep( IP地址::::from_string(), 2001);
IP::TCP::套接字 胶皮管(维修)
(EP)

率先,你的挨次反正呼唤一任一某一io_service范例。运用io_service与监控体系的输入/输入维修的变换。通常一任一某一io_service这样地榜样就十足了。。同时,安排要衔接的地址和持枪,再次设置套接字。将套接字衔接到您安排的地址和持枪。

上面是一任一某一简略的维修军事]野战的:

typedef boost::shared_ptr socket_ptr;
io_service service;
IP::TCP::极窘迫的境地 ep( ::::V4 TCP IP, 2001)); // listen on 2001
IP:TCP::接受者 ACC(维修, EP)
while ( 真的) {
    socket_ptr (新胶皮管 IP::TCP::套接字(service));
    胶皮管)
    线索: 提高::绑定(client_session, 胶皮管)
}
void client_session(socket_ptr 胶皮管) {
    while ( 真的) {
        char data[512];
        size_t len = 胶皮管-> read_some(缓冲剂(履历)
        if ( len > 0)
            写(*), 缓冲剂(OK), 2));
    }
}

率先,它还呼唤反正一任一某一io_service范例。同时指派要监听的持枪。,安排一任一某一接纳客户端衔接的情郎。 鄙人一任一某一整数的中,安排笨蛋套接字等候客户端衔接。。同时使成为衔接时,您安排一任一某一线索来处置此衔接。。

在client_session在线索中读取客户机的召唤。,举行解析,同时统计表算是。

安排异步客户端,您呼唤处决以下处理或许诺:

using boost::日博开户;
io_service service;
IP::TCP::极窘迫的境地 ep( IP地址::::from_string(), 2001);
IP::TCP::套接字 胶皮管(维修)
(EP, connect_处置挨次);
();
void connect_handler(const ::::error_code助推体系 & EC) {
    // 如果EC成统计表,咱们可以变卖衔接是成的。
}

在挨次中,您呼唤安排反正一任一某一io_service范例。您呼唤指派衔接的地址并安排套接字。。

当衔接抛光(抛光处置挨次),你将轻易,执意说,connect_handler高音调的。

connect_handler当祈求救助,反省错误的密码ec),如果成,可以向维修性的构图异步构图。。

注重:只贫穷一任一某一异步处理或许诺呼唤处置。,()这样地时期将一向在运转。。在上面的榜样中,假如一任一某一如此的处理或许诺被处决。,它的插座。async_connect。在这以后的,()不料退职。。

每个异步处理或许诺都有一任一某一填写的处置器——一任一某一名为AFT的职务。。 上面的密码是根本的异步维修性的端

using boost::日博开户;
typedef boost::shared_ptr socket_ptr;
io_service service;
IP::TCP::极窘迫的境地 ep( ::::V4 TCP IP, 2001)); // 监听持枪2001
IP:TCP::接受者 ACC(维修, EP)
socket_ptr (新胶皮管 IP::TCP::套接字(service));
start_accept(胶皮管);
();
void start_accept(socket_ptr 胶皮管) {
    (*sock, 绑定 handle_accept, sock, _1) );
}
void handle_accept(socket_ptr sock, const ::::error_code助推体系 &
ERR) {
    if ( ERR) return;
    // 从在这一点上开端, 你可以从插座上读或写。
    socket_ptr (新胶皮管 IP::TCP::套接字(service));
    start_accept(胶皮管);
}

在上面的密码段中,率先,你安排一任一某一io_service范例,指派要监督的持枪。同时,你安排一任一某一接纳器ACC -一任一某一客户端衔接,安排笨蛋套接字,异步等候客户端衔接的情郎。。

至死,运转的异步()整数的。当接纳到客户端衔接时,handle_accept工具(工具async_accept填写的处置挨次)。如果没错误的,这样地插座可以用来读写。。

运用此套接字后,您安排了一任一某一新的套接字,同时再工具start_accept(),安排另一任一某一等候客户端衔接的异步处理或许诺,列举如下使()整数的跑跑颠颠。

非常处置与错误的密码

容许同时运用非常处置或错误的密码。,承认的异步职务过载提出成绩错误的的两种办法。当职务提出成绩错误的时,它通常会提出成绩::::system_error助推体系的错误的。

using boost::日博开户;
IP::TCP::极窘迫的境地 ep;
IP::TCP::套接字 胶皮管(维修)
(EP) // 第共同的
::::error_code助推体系 err;
(EP, ERR); // 第二的行

在先前的密码中,(EP)一任一某一错误的将被提出成绩,(EP, ERR)同时统计表错误的密码。。

请看上面的密码划分:

try {
    (EP)
} catch(::::system_error助推体系 e) {
    std::cout << () << std::endl;
}

上面的密码划分与后面的密码划分异样地:

::::error_code助推体系 err;
(EP, ERR);
if ( ERR)
    std::cout << err << std::endl;

运用异步职务时,您可以在回调职务中反省它统计表的错误的密码。。异步职务一点也不提出成绩非常。,由于如此做毫无意思。。谁会诱惹它?

在异步职务中,您可以运用非常处置或错误的密码(如您所愿),又要供养同种。同时,运用这两种办法能够会落得成绩。,大分离工夫都是撞车(当你不谨慎误审的的时分。,遗忘处置提出成绩的非常。。如果你的密码非常赞许地复杂(祈求救助丰盛的的socket读写职务),您最好选择非常处置的方法。,把你的标明和构图包罗在一任一某一职务中。try {} catch块内。

void client_session(socket_ptr 胶皮管) {
    try {
        ...
    } catch ( ::::system_error助推体系 e) {
        // 处置错误的
    }
}

如果运用了错误的密码,你可以使运用以下密码段检测当衔接CLO:

char data[512];
::::error_code助推体系 error;
size_t length = (缓冲剂(履历)), 错误的)
if (错误的 == 错误的::EOF)
    return; // 衔接紧密的

的承认错误的码都遏制在ˆ的命名余地中(俾你使掉转船头一任一某一玩个痛快的switch来反省错误的的认为)。如果你想变卖更多的特殊性,请参照boost/日博开户/头纸

击中要害线索

当屈尊做某事线索时,咱们常常议论。:

  • io_service:io_service它是线索包管的。可以同时祈求救助专有的线索。io_service::run()。在块使适应下,可以祈求救助单线索职务。io_service::run(),此职务必需等候承认异步处理或许诺在处决前处决。。尽管如此,在世界上,可以在多线索中祈求救助它。io_service::run()。这将忍住承认呼叫。io_service::run()的线索。假如它击中要害无论哪个线索被祈求救助io_service::run(),承认的回调被祈求救助的同时;这就断言。,当你祈求救助一任一某一线索io_service::run()时,承认的回调都高音调的。
  • socket:socket类不它是线索包管的。因此,您预料预防读取线索击中要害套接字。,它在另一任一某一线索中同时构图它。。(通常不马夫这种处理或许诺。)。,更不用说了。。
  • utility:就utility来说,由于它不它是线索包管的,如此,通常不倡议同时运用多线索。。外面的办法常常在很短的工夫内运用。,同时它被投递。。

要责任你本人使掉转船头的线索,它还遏制专有的线索。。但可以确保这些线索不祈求救助您的密码。。它也断言,假如工具io_service::run()办法的线索祈求救助回调职务。。

不独仅是办法通信工具

要责任办法通信工具,它还遏制如此以及其他I/O效能。。

供养臂板打猎系统,譬如SIGTERM(软件结束)、SIGINT(拦截打猎)、SIGSEGV(段措武)等。 你可以安排一任一某一signal_set范例,指派异步等候的臂板打猎系统。,同时当这些打猎发生时,您将祈求救助异步处置挨次。:

void signal_handler(const ::::error_code助推体系 & err, int 打猎)
{
    // 纪录日记,同时中断涂挨次
}
boost::日博开户::signal_set SIG(Service, SIGINT, SIGTERM);
(signal_处置挨次);

如果SIGINT发生,你可以在你的signal_handler在回调中被卡住它。

您可以很轻易地衔接到串行持枪。。Windows上的持枪专门名称是COM7,在POSIX平台是/dev/ttyS0

io_service service;
serial_port SP(维修, "COM7");

掩护吐艳后,您可以运用以下密码设置稍许的持枪选择权,诸如,持枪的波特率。、奇偶性和中止位。

serial_port::baud_rate rate(9600);
(率)

掩护吐艳后,您可以将这样地串行持枪处理一任一某一流。,同时它运用自在职务读取/构图串行持枪。。譬如async_read(), write, async_write(), 像上面的密码划分:

char data[512];
读(SP, (履历缓冲剂, 512));

也可以衔接到Windows的纸,同时运用异样地的自在职务,譬如read(), asyn_read()以及其他,像上面的密码划分:

HANDLE h = ::OpenFile(...);
windows::stream_handle SH(维修, h);
char data[512];
读(H, (履历缓冲剂, 512));

为poxis纸周转符,诸如,一根管子,基准的I/O和承认的安装(但责任普通的纸)都可以做到。,列举如下密码:

posix::stream_descriptor sd_in(service, ::dup(STDIN_FILENO));
char data[512];
read(sd_in, (履历缓冲剂, 512));

点火调节装置

稍许的I/O处理或许诺呼唤额外的时间工夫。。这可是涂于异步处理或许诺(同时性方法B),因此没额外的时间工夫。。诸如,下一任一某一音讯必需从100给你的伴侣给你。

bool read = false;
void deadline_handler(const ::::error_code助推体系 &) {
    std::cout << (read ? "read successfully" : "read failed") << std::endl;
}
void read_handler(const ::::error_code助推体系 &) {
    read = true;
}
IP::TCP::套接字 胶皮管(维修)
…
read = false;
char data[512];
((履历缓冲剂, 512));
deadline_timer T(维修, boost::posix_time::milliseconds(100));
(&deadline_处置挨次);
();

在上面的密码段中,如果您在额外的时间前读取履历,read它设置为true。,因此咱们的合伙人即时告知了咱们。。要不然,当deadline_handler当祈求救助,read或假,这断言咱们的行为曾经老一套了。。

它还供养同时性电键器。,但它们通常与简略的宁静处理或许诺异样地。。boost::this_thread::sleep(500);这样地密码和上面的密码划分做了异样的事实。:

deadline_timer T(维修, boost::posix_time::milliseconds(500));
();

io_service类

您必然要曾经瞥见,使安定中运用的块密码都将运用稍许的密码。io_service的范例。io_service这是藏书里最要紧的指引航线。;它许诺处置监控体系。,等候承认异步处理或许诺的完毕,同时为每个异步处理或许诺祈求救助它的抛光处置挨次。。

如果选择以同时性方法安排涂挨次,你则不呼唤思索我将在这一节向你表明的东西。
你有多种办法可以运用io_service。在上面的榜样中,咱们有3个异步处理或许诺,2个套接字衔接处理或许诺和一任一某一电键器等候处理或许诺:

  • 有一任一某一io_service示例和用于处置线索的单线索示例:
    io_service service; // 承认套接字处理或许诺都由维修处置。 
    IP::TCP::套接字 sock1(service); // all the socket operations are handled by service 
    IP::TCP::套接字 sock2(service); ( ep, connect_处置挨次); 
    ( ep, connect_处置挨次); 
    deadline_timer T(维修, 提高::::posixtime秒(5)
    (timeout_处置挨次); 
    ();
    
  • 一任一某一多线索的榜样有io_service范例和多个处置日:
io_service service;
IP::TCP::套接字 sock1(service);
IP::TCP::套接字 sock2(service);
( ep, connect_处置挨次);
( ep, connect_处置挨次);
deadline_timer T(维修, 提高::::posixtime秒(5)
(timeout_处置挨次);
for ( int i = 0; i < 5; ++i)
    线索: run_service);
void run_service()
{
    ();
}
  • 有多个io_service用于处置线索的示例和多线索示例:
io_service 维修[ 2 ]
IP::TCP::套接字 sock1(维修[ 0 ]
IP::TCP::套接字 sock2(维修[ 1 ]
( ep, connect_处置挨次);
( ep, connect_处置挨次);
deadline_timer T(维修[0], 提高::::posixtime秒(5)
(timeout_处置挨次);
for ( int i = 0; i < 2; ++i)
    线索: 绑定run_service, i));
void run_service(int idx)
{
    service[idx].run();
}

率先,要认识到你不克不及拿不已一任一某一。io_service范例中假如一任一某一线索。。上面的密码划分没意思:

for ( int i = 0; i < 2; ++i)
    service[i].run();

上面的密码划分毫无意思,由于维修[ 1 ]运转呼唤维修[ 0 ]运转先完毕。如此,承认的维修[ 1 ]处置的异步处理或许诺都在等候。,这显然责任个好主意。。

在先前的3个计划中,咱们正等候3个异步处理或许诺完毕。。解说它们暗中的分别,咱们装出:少,处理或许诺1抛光了。,同时处理或许诺2抛光。。同时,咱们装出每个抛光的处置器呼唤1秒到。

在第一任一某一榜样中,咱们等候三个处理或许诺在一任一某一线索中抛光。,基本的处理或许诺抛光,咱们称其为抛光处置挨次。。纵然处理或许诺2同时抛光,又处理或许诺2的抛光处置挨次呼唤1秒以后的。,执意说,当抛光处理或许诺时祈求救助处理或许诺1的抛光处置挨次。。

第二的例,咱们等候3个异步处理或许诺以两个线索完毕。当处理或许诺1抛光时,咱们在第一任一某一线索中祈求救助它的抛光处置挨次。。当处理或许诺2抛光时,接着,咱们就在第2个线索中祈求救助它的抛光处置挨次(当线索1在忙着回应经文处理或许诺1的处置挨次时,线索2是无意义的的,可以对无论哪个新的传入处理或许诺作出回应经文。。

在第三例,由于处理或许诺1是sock1connect,2是处理或许诺sock2connect,因此涂挨次会体现得像第二的例俱。线索1将处置sock1connect处理或许诺的抛光处置挨次,线索2将处置sock2connect处理或许诺的抛光处置挨次。尽管如此,如果sock1connect处理或许诺是处理或许诺1,deadline_timer t额外的时间处理或许诺是处理或许诺2。,线索1将以处置完毕sock1connect处理或许诺的抛光处置挨次。因此,deadline_timer t额外的时间处理或许诺必需等候。sock1connect处理或许诺的抛光处置挨次曾经抛光(等候1秒)。,由于线索1是要处置的sock1衔接处置器和t额外的时间处置挨次。

上面是你呼唤详细地检查的前一任一某一榜样:

  • 第一任一某一是非常赞许地根本的涂挨次。。由于这是一任一某一延续的方法,如此,当呼唤同时祈求救助多个处置器时,你通常碰撞瓶颈路段。如果处置挨次呼唤很长工夫才干处决,承认后续处置挨次都必需等候。
  • 第二的种使适应是更适宜的涂挨次。。他很壮大,如果在同一任一某一提姆上祈求救助专有的处置挨次,他们在各自的线索中被祈求救助。。单独的的瓶颈路段是承认的处置线索都是忙碌的和新的处置挨次。。尽管如此,这是一任一某一走得快的解决计划。,扩大处置线索的总计。
  • 第三是最复杂和最难懂的。。假如当你不克不及使满足第二的个召唤时,才运用它。。这种使适应普通执意当你有不计其数实时(socket)衔接时。您可以思索每个处置线索(运转)io_service::run()线索)有本人的select/epoll整数的;它等候无论哪个套接字衔接。,同时等候读写处理或许诺。,当瞥见这样地处理或许诺时,在处决。大分离使适应下,你不用焦虑什么,单独的你呼唤焦虑的执意当你监控的socket数量以目录级的方法增长时(超越1000个的socket)。在那种使适应下,有多个选择/ epoll整数的扩大的回应经文工夫。

如果你觉得你的涂挨次能够呼唤替换到第三种榜样,请确保此段密码监督处理或许诺(祈求救助)。io_service::run()涂挨次的密码是从涂挨次的如此以及其他分离保护,因此你可以很轻易地使变换它。

至死,呼唤记得的是,如果没如此以及其他的监控体系,.run()它将完毕,像上面的密码划分:

io_service service; 
套接字:套接字 胶皮管(维修) 
( ep, connect_处置挨次); 
();

在上面的榜样中,假如胶皮管曾经使成为了衔接,connect_handler这将高音调的,同时()处决将抛光。。

如果你希望()同时处决,你呼唤给它分派更多的任务。。变卖这一目的有两种办法。。同上路在connect_handler启动另一任一某一异步处理或许诺来分派更多的任务。 其他的办法是模仿其击中要害稍许的任务。,运用以下密码段:

typedef boost::shared_ptr work_ptr;
work_ptr dummy_work(new io_service::任务(维修)

前述事项密码可以开始包管。()一向积累到你工具为止()或许 (0);// 销毁 dummy_work.

总结

作为一任一某一复杂的藏书,使办法预调非常赞许地简略。修建起来很简略。并完成预防运用宏的任务。;它限制了专有的宏来处决选择权软鞭子。,但你呼唤少关怀。

供养同时性和异步预调。他们非常赞许地区分。;你呼唤在放映的最初选择流行一任一某一来变卖。,由于它们暗中的替换非常赞许地复杂同时轻易出错。。

如果您选择同时性,您可以选择非常处置或错误的密码。,从非常处置定位错误的密码;只需在祈求救助职务中添加一任一某一限制因素(错误的密码)。

不合理的办法预调。它更如此以及其他稍许的特点。,它使它更罪状。,诸如,打猎灯,电键器等。

鄙人一章中咱们将便笺丰盛的的职务和类。咱们还将详细地检查异步预调的稍许的诡计。。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Message *
Name*
Email *