boost::asio异步收消息

需求背景说明,boost::asio网络编程库,在进行同步收发消息的时候,本身是不支持超时的。如果自己想尝试去实现,给同步收消息增加一个超时,会有一系列弊端,比如额外的工作量,简单的代码变得不好看,程序可能变得不稳定。同时,在高并发情况下,就更是需要使用异步收消息来提升性能,开更少的线程去做更多的事。本人能力有限,本文只介绍boost::asio异步收消息的基本使用。

 

要想实现异步操作,就需要提供一个环境,这个环境是

boost::asio::io_service io_service_;

io_service_.run();

但是io_service_.run(),是不阻塞的,这个环境是需要io_service_.run()阻塞运行的,于是需要改成这样

boost::asio::io_service io_service_;

boost::asio::io_service::work work_(io_service_);

io_service_.run();

用io_service构造出一个work之后,再执行io_service_.run();就是阻塞的了。但是主线程不可以阻塞,否则后面的代码没法执行了,于是需要继续改

boost::asio::io_service io_service_;

boost::asio::io_service::work work_(io_service_);

boost::thread th(run_io);

void run_io()

{

    io_service_.run();

}

使用boost::thread来开启一个线程,线程的入口函数就是run_io。为了简化传递参数io_service_给线程,将io_service_声明为全局变量,就不用传参了。以上代码,包含头文件boost/asio.hpp,boost/thread.hpp。

执行io_service_.stop();,io_service_.run();就会结束。一般在程序结束的时候,执行io_service_.stop();。

 

下面准备写一个客户端,和一个服务器。客户端和服务器都得写,才能方便调试,才能真正学会。

服务器侦听本地666端口,开启异步操作,异步收到一条消息打印出来,然后同步返回一条消息,“hello client”。

客户端连接本地666端口,连接服务器后,开启异步操作,同步发送一条消息,“hello server”,异步收到消息后,也打印出来。

为了简化,客户端和服务器都非常得简单,重点是研究异步操作怎么用,去感受理解它的原理。

 

代码参考如下,可直接编译运行。为了简化传参,尽量使用了全局变量,实际使用,是尽量不要使用全局变量的。

客户端

#include <boost/asio.hpp>
#include <boost/thread.hpp>


boost::asio::io_service io_service_;
boost::asio::ip::tcp::socket socket_(io_service_);

void async_read_head(const boost::system::error_code& error, size_t bytes_transferred);
void run_io();
char buf[16] = {};
std::string s = "hello server";

int main()
{
    boost::asio::io_service::work work_(io_service_);
    boost::thread th(run_io);
    
    boost::asio::ip::tcp::endpoint endpoint_(
        boost::asio::ip::address::from_string("127.0.0.1"), 666);
    boost::system::error_code ec;
    socket_.connect(endpoint_, ec);
    if (ec)
    {
        socket_.close();
        return 0;
    }

    // 异步读消息
    boost::asio::async_read(socket_, boost::asio::buffer(buf, 16),
        boost::bind(async_read_head, boost::asio::placeholders::error, 
            boost::asio::placeholders::bytes_transferred));

    // 发送消息
    memset(buf, 0, 16);
    memcpy(buf, s.c_str(), s.length());
    int sum = 0, pos = 0;
    while (sum < 16)
    {
        pos = socket_.write_some(boost::asio::buffer(buf + sum, 16 - sum), ec);
        sum += pos;
        if (pos == 0)
        {
            return 0;
        }
    }

    getchar();
    io_service_.stop();
    socket_.close();
    return 0;
}


void run_io()
{
    io_service_.run();
}

void async_read_head(const boost::system::error_code& error, size_t bytes_transferred)
{
    printf("recv length : %d \n", bytes_transferred);
    printf("%s \n", buf);
}


服务器

#include <boost/asio.hpp>
#include <boost/thread.hpp>

// 异步收消息,同步返回消息

boost::asio::io_service io_service_;
boost::asio::ip::tcp::socket socket_(io_service_);
void run_io();

void handle_accept(const boost::system::error_code& error);
void handle_read(const boost::system::error_code& error, size_t bytes_transferred);
void handle();

char buf[16] = {};
std::string s = "hello client";

int main()
{
    boost::asio::io_service::work work_(io_service_);
    boost::thread th(run_io);
    boost::asio::ip::tcp::endpoint endpoint_(boost::asio::ip::address::from_string("0.0.0.0"), 666);
    boost::asio::ip::tcp::acceptor acceptor_(io_service_, endpoint_);

    // 异步接收请求
    acceptor_.async_accept(socket_, boost::bind(handle_accept, boost::asio::placeholders::error));

    getchar();
    io_service_.stop();
    socket_.close();
    return 0;
}

void run_io()
{
    io_service_.run();
}

void handle_accept(const boost::system::error_code& error)
{
    if (error)
    {
        return;
    }
    // 异步收到请求后,继续异步收消息
    boost::asio::async_read(socket_, boost::asio::buffer(buf, 16),
        boost::bind(handle_read, boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
}

void handle_read(const boost::system::error_code& error, size_t bytes_transferred)
{
    printf("recv length : %d \n", bytes_transferred);
    printf("%s \n", buf);
    handle();
}

void handle()
{
    // 返回 hello client
    memset(buf, 0, 16);
    memcpy(buf, s.c_str(), s.length());
    int sum = 0, pos = 0;
    boost::system::error_code ec;
    while (sum < 16)
    {
        pos = socket_.write_some(boost::asio::buffer(buf + sum, 16 - sum), ec);
        sum += pos;
        if (pos == 0)
        {
            return;
        }
    }
}


 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值