Boost asio的async_write函数输入日志标题

本文详细解析了在使用Boostasio库的async_write函数时,不正确的使用方式可能导致的数据混乱问题,并提供了正确的实现方法,确保接收端能够依次正确接收数据块。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Boost asio是一个异步网络通信的库,其中async_write是一个比较常用的函数,但是,如果没有正确的使用,就可能会出现一些意想不到的潜在Bug。例如下面的代码:

   1:  for (int i=0; i < n; i++)

   2:  {

   3:      boost::asio::async_write(

   4:          socket_,

   5:          boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),

   6:          boost::asio::transfer_at_least(buffer[i].length_),

   7:          boost::bind(

   8:              &HttpServer::HandleTcpSend,

   9:              shared_from_this(),

  10:              boost::asio::placeholders::error,

  11:              boost::asio::placeholders::bytes_transferred

  12:          )

  13:      );

  14:      // Do something

  15:  }

 

代码很简单,就是循环N次,发送N块buffer。我们的目标是,接收端依次接收buffer1,buffer2,……,buffer n。但是,事实上,上面的代码是有问题的,服务器可能会接收到完全错乱的数据。先看一下正确的写法,代码如下:

   1:  int i=0;

   2:  boost::asio::async_write(

   3:      socket_,

   4:      boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),

   5:      boost::asio::transfer_at_least(buffer[i].length_),

   6:      boost::bind(

   7:          &HttpServer::HandleTcpSend,

   8:          shared_from_this(),

   9:          boost::asio::placeholders::error,

  10:          boost::asio::placeholders::bytes_transferred

  11:      )

  12:  );

  13:  &#160;

  14:  // Do something

  15:

  16:  void HttpServer::HandleTcpSend(const boost::system::error_code& err,

  17:      size_t bytes_transferred)

  18:  {

  19:      i++;

  20:      boost::asio::async_write(

  21:          socket_,

  22:          boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),

  23:          boost::asio::transfer_at_least(buffer[i].length_),

  24:          boost::bind(

  25:              &HttpServer::HandleTcpSend,

  26:              shared_from_this(),

  27:              boost::asio::placeholders::error,

  28:              boost::asio::placeholders::bytes_transferred

  29:          )

  30:      );

  31:  }

 

也就是在第一个buffer发成功之后,再发送第二个buffer,依次类推。为什么一定要这样写呢?首先,看一下async_write是怎么实现的,aysnc_write里面调用async_write_some函数。也就是说,async_write一次数据发送,并一定把所有的数据都发送完,有可能async_write一次就发其中的一部分。那么,如果在第一个async_write还没有发送完毕之后,从第二个async_write发送数据,势必导致接收端接收的数据有问题。这个并不是asio的限制,底层套接字的一些函数,如发送等也无法保证一次异步操作就把所有的数据都通过TCP流发送出去。async_write将被告知有多少字节实际发送了,然后要求在下一次异步操作时发送剩余的字节。async_write是通过一次或者多次调用async_write_some函数来实现的,那么如果在第一个async_write还没有完成就调用第二个async_write,async_write_some就有可能先将第二个buffer的数据先发送出去。

因此,NEVER start your second async_write before the first has completed.

转载于:https://my.oschina.net/jacobin/blog/298544

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值