我搜索了其他帖子,但没有发现任何相关内容。 现在,我有一个由标题和正文组成的协议。 协议如下: Z24,91009802,123456789ABCDEF 其中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_中,但我认为调用不会检查这个吗?
这是输出中的转储:
请求_ =#Z24,# 为nbytes = 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;
}
}
答案 0 :(得分:2)
The Boost ASIO documentation表示async_read_until调用可能会将数据读入超出分隔符的缓冲区(请参阅“备注”部分)。话虽如此,根据您的输入,您检查缓冲区是否有更多数据的解决方案是一个很好的解决方案。
正如我在上面的评论中提到的,如果您的要求允许您这样做,那么使用剩余字节的整数值而不是字符串可能会让您的生活更轻松,代码更清晰,错误更少易发生。
答案 1 :(得分:1)
async_read_until
可以读取字节past the delimiter
说明
成功的async_read_until之后 操作,streambuf可能包含 超出分隔符的其他数据。 申请通常会离开 在streambuf中的数据 后续的async_read_until操作 检查。