Boost asio的async_write函数
来源:互联网 发布:建筑工程绘图软件 编辑:程序博客网 时间:2024/05/21 06:21
Boost asio是一个异步网络通信的库,其中async_write是一个比较常用的函数,但是,如果没有正确的使用,就可能会出现一些意想不到的潜在Bug。例如下面的代码:
[cpp] view plaincopy
for (int i=0; i < n; i++)
{
boost::asio::async_write(
socket_,
boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),
boost::asio::transfer_at_least(buffer[i].length_),
boost::bind(
&HttpServer::HandleTcpSend,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
// Do something
}
代码很简单,就是循环N次,发送N块buffer。我们的目标是,接收端依次接收buffer1,buffer2,……,buffer n。但是,事实上,上面的代码是有问题的,服务器可能会接收到完全错乱的数据。先看一下正确的写法,代码如下:
[cpp] view plaincopy
int i=0;
boost::asio::async_write(
socket_,
boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),
boost::asio::transfer_at_least(buffer[i].length_),
boost::bind(
&HttpServer::HandleTcpSend,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
// Do something
void HttpServer::HandleTcpSend(const boost::system::error_code& err,
size_t bytes_transferred)
{
i++;
boost::asio::async_write(
socket_,
boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),
boost::asio::transfer_at_least(buffer[i].length_),
boost::bind(
&HttpServer::HandleTcpSend,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
也就是在第一个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.上一篇:C++开发者的VS2010(二)—— Lambda 表达式 下一篇:OpenGL实用开源代码列表
[cpp] view plaincopy
for (int i=0; i < n; i++)
{
boost::asio::async_write(
socket_,
boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),
boost::asio::transfer_at_least(buffer[i].length_),
boost::bind(
&HttpServer::HandleTcpSend,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
// Do something
}
代码很简单,就是循环N次,发送N块buffer。我们的目标是,接收端依次接收buffer1,buffer2,……,buffer n。但是,事实上,上面的代码是有问题的,服务器可能会接收到完全错乱的数据。先看一下正确的写法,代码如下:
[cpp] view plaincopy
int i=0;
boost::asio::async_write(
socket_,
boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),
boost::asio::transfer_at_least(buffer[i].length_),
boost::bind(
&HttpServer::HandleTcpSend,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
// Do something
void HttpServer::HandleTcpSend(const boost::system::error_code& err,
size_t bytes_transferred)
{
i++;
boost::asio::async_write(
socket_,
boost::asio::buffer( buffer[i].data_.get(), buffer[i].length_ ),
boost::asio::transfer_at_least(buffer[i].length_),
boost::bind(
&HttpServer::HandleTcpSend,
shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred
)
);
}
也就是在第一个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.
- Boost asio的async_write函数
- Boost asio的async_write函数
- Boost asio的async_write函数
- 关于boost::asio::async_write的实现机制
- boost::asio::async_write() versus boost::asio::write()
- boost asio async_write : how to not interleaving async_write calls?
- boost asio async_write : how to not interleaving async_write calls?
- boost::asio async_write也不能保证一次发完所有数据 一
- boost::asio async_write也不能保证一次发完所有数据 二
- boost::asio发送与传输相关的几个函数,备忘
- boost::asio::io_service的stop()和reset()和stopped()函数
- ASIO与BOOST::ASIO的不同之处
- Boost.Asio的基本剖析(Basic Boost.Asio Anatomy)
- Boost下强大的asio
- boost的网络库asio
- boost::asio 的同步方式
- boost::ASIO的异步方式
- UDP boost::asio的实现
- 频差
- flex扫盲篇
- c++中vector的使用
- ExtJS4.1+MVC3+Spring.NET1.3+EF5 整合六:业务逻辑层
- Delphi VCL 的消息处理机制(1)
- Boost asio的async_write函数
- 各数据类型转换byte数组(方便java和c++的网络通信)
- win7 Oracle 10g 卸载说明(备注)
- android-JNI学习记录(1)
- Java表达式求值
- 积累
- Android教程(一)-- 环境搭建
- 错误提示: Debug Assertion Failed! Program:... File:fclose.c Expression: (stream!=NULL)
- c++交换数据所用的两种方法