当streambuf由以前的async_read填充时,boost::asio::async_read::streamb
boost::asio::async_read into boost::asio::streambuf blocks when streambuf is populated by previous async_read
我搜索过其他帖子,但没有找到任何相关的内容。现在,我有一个由标头和正文组成的协议。协议类似于:z2491009802123456789bcdef其中Z24,是收割台。Z是消息类型,24是要读取的剩余字节。剩余的字节是可变的,所以我一直读到找到第一个","。
void handle_handshake(const boost::system::error_code& error)
{
if (!error)
{
boost::asio::async_read_until(
socket_,
inputStreamBuffer_,
',',
boost::bind(
&session::doReadHeader, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
);
}
else
{
delete this;
}
}
void doReadHeader(
const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
istream is(&inputStreamBuffer_);
vector<char> v(bytes_transferred);
is.read(&(v[0]),bytes_transferred);
request_.append(v.begin(),v.end());
cout << "request_=#" << request_ << "#" << endl;
int nBytes=string_to_llint(request_.substr(1,request_.size()-2));
cout << "nBytes=" << nBytes << endl;
cout << "size=" << inputStreamBuffer_.size() << endl;
boost::asio::async_read(
socket_,
inputStreamBuffer_,
boost::asio::transfer_at_least(nBytes),
boost::bind(
&session::doReadBody, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
);
}
else
{
delete this;
}
}
void doReadBody(
const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
istream is(&inputStreamBuffer_);
vector<char> v(bytes_transferred);
is.read(&(v[0]),bytes_transferred);
request_.append(v.begin(),v.end());
string response=cardIssueProcessor_.process(request_);
cout << "request=#" << request_ << "#" << endl;
cout << "response=#" << response << "#" << endl;
request_.clear();
boost::asio::async_write(
socket_,
boost::asio::buffer(response, response.size()),
boost::bind(
&session::doWriteResponse, this,
boost::asio::placeholders::error)
);
}
else
{
delete this;
}
}
现在,读取标题。但是读取页脚会阻塞。显然,整个消息都在标头调用中读取。当我用boost::asio::transfer_at_least(nBytes)执行第二个async_read()时,nBytes已经在inputStreamBuffer_中,但我认为调用没有检查这一点?
这是输出的转储:
request_=#Z24#n字节=24大小=24
问题出在哪里,或者我该如何解决。我是一个新手,所以感谢所有的帮助。非常感谢。
编辑:我试着检查缓冲区的填充情况,如果上一次调用已经读取了正文,就不要对其进行async_read()调用。这是可行的,但这是正确的解决方案吗?
void doReadHeader(
const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
istream is(&inputStreamBuffer_);
vector<char> v(bytes_transferred);
is.read(&(v[0]),bytes_transferred);
request_.assign(v.begin(),v.end());
cout << "request_=#" << request_ << "#" << endl;
int nBytes=string_to_llint(request_.substr(1,request_.size()-2));
cout << "nBytes=" << nBytes << endl;
cout << "size=" << inputStreamBuffer_.size() << endl;
size_t toReadBytes=nBytes-inputStreamBuffer_.size();
if (toReadBytes>0)
{
boost::asio::async_read(
socket_,
inputStreamBuffer_,
boost::asio::transfer_at_least(toReadBytes),
boost::bind(
&session::doReadBody, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)
);
}
else
{
doReadBody(error,nBytes);
}
}
else
{
delete this;
}
}
Boost ASIO文档指出async_read_until调用可能会将超出分隔符的数据读取到缓冲区中(请参阅备注部分)。也就是说,考虑到您的输入,检查缓冲区是否有更多数据的解决方案是一个很好的解决方案。
正如我在上面的评论中提到的,如果您的需求允许您这样做,那么使用剩余字节的整数值而不是字符串可能会让您的生活更轻松,代码也更干净,不容易出错。
async_read_until
可以读取超过分隔符的字节
备注
async_read_until成功后操作,streambuf可能包含分隔符之外的其他数据。申请通常会离开streambuf中的数据后续async_read_until操作检查。
- 为什么std::async使用同一个线程运行函数
- 为什么可以将左值传递给"std::async",即使它引用了右值
- 使用用户定义的参数调用future/async并调用类方法
- 使用 ImageIO.read() 生成的图像是否仍然使用传递给它的相同内存?
- std::ifstream::read 不会读取所有 512 字节,并设置 EOF 和失败位
- 使用 std::async 时死锁,将来作为成员
- 为什么我不能将引用作为 std::async 的函数参数传递
- std::async from std::async in windows xp
- Google Cloud Pubsub Async Streaming API in C++
- write() 和 read() 中几乎没有混淆
- C++ TCP 套接字通信 - 连接按预期工作,几秒钟后失败,没有收到新数据,read() 和 recv() 块
- -fno-unwind-tables 和 -fno-async-unwind-tables 不起作用 NDK clang
- 为什么调试器引发"read access violation. this was nullptr"异常?
- 对同一文件使用 .read 的次数是否有限制?
- Win32 API - HWND "{unused = ???} Unable to read memory"错误
- 为什么我会"Invalid read of size 8"?(瓦尔格林德)
- std::async 如何工作:为什么它会调用这么多次复制/移动?
- QDataStream read to QVector
- asio::read() 需要很长时间,使用 asio::write 没有问题
- Read OpenCV Mat 16bit to QImage 8bit Greyscale