boost 库asio网络接口收取数据缺失的分析
2017-11-04 12:16
781 查看
为了实现一个收到HTTPS响应的接口,我的实现思路是这样的:
分三步对响应进行接收,第一步先接收response_line, 第二步接收response_header , 最后一步对reponse_body进行接收。
在代码上,因为前两步都有明显的结束标识符,response line使用"\r\n"作为结束标识库,response header使用"\r\n\r\n"作为结束标识库,这些都是HTTP标准规定的,所以不会有问题,而response body使用一个计时器,当接收超时100ms后,表示当前body已经接收完成。
代码逻辑如下:
读取response line:
asio::async_read_until(socket_,
response_,
MatchResponseLine,
bind(&HttpsWebClient::OnReadResponseLineHandler,
this,
web_response,
response_handler,
asio::placeholders::error,
asio::placeholders::bytes_transferred)
);
MatchResponseLine中对"\r\n"进行遍历,找到就返回相应的response_迭代器位置,然后读取完成后调用回调函数OnReadResopnseLineHandler
读取reponse header:
asio::async_read_until(socket_,
response_,
MatchResponseHeader,
bind(&HttpsWebClient::OnReadResponseHeaderHandler,
this,
web_response,
response_handler,
asio::placeholders::error,
asio::placeholders::bytes_transferred)
);
解析如上。
读取response body:
socket_.async_read_some(
asio::buffer(read_data_buffer_, READ_DATA_BUFFER_SIZE),
bind(&HttpsWebClient::OnReadResponseBodyHandler, this,
web_response,
response_handler,
asio::placeholders::error,
asio::placeholders::bytes_transferred)
这三次调用是顺序调用的,也就是在OnReadResponseLineHandler中调用了read response header, 然后在OnReadResonseHeaderHandler中调用了read reponse body.
然后就出现了问题,当读取reponse line和reponse body时就能够正常的拿到所有数据。但最后一步读取reponse body的时候就发现body的前120个字节不见了。
一开始以为是boost 的 asyn_read_some接口出问题了,上google查了下发现没有人有遇到类似的问题,但还是换了下接口,换成asyn_read,改了下相关的逻辑,发现没有办法解决问题。于是就开始怀疑是缓冲区的处理的问题,
使用单步调试进入MatchResponseHeader中,发现在read response header的时候就已经把body的一部分数据读到了response_缓冲区中了,而当我们去读body的时候,使用了另外一个缓冲区read_data_buffer_缓冲区,导致了body开头的数据丢失。
所以发现问题后,解决方法就是在read response body中也使用相同的response_缓冲区。
修改后的代码如下:
asio::async_read(socket_,
response_,
//asio::buffer(read_data_buffer_,
READ_DATA_BUFFER_SIZE),
boost::asio::transfer_at_least(1),
bind(&HttpsWebClient::OnReadResponseBodyHandler,
this,
web_response,
response_handler,
asio::placeholders::error,
asio::placeholders::bytes_transferred)
);
验证后证明是OK的。
分三步对响应进行接收,第一步先接收response_line, 第二步接收response_header , 最后一步对reponse_body进行接收。
在代码上,因为前两步都有明显的结束标识符,response line使用"\r\n"作为结束标识库,response header使用"\r\n\r\n"作为结束标识库,这些都是HTTP标准规定的,所以不会有问题,而response body使用一个计时器,当接收超时100ms后,表示当前body已经接收完成。
代码逻辑如下:
读取response line:
asio::async_read_until(socket_,
response_,
MatchResponseLine,
bind(&HttpsWebClient::OnReadResponseLineHandler,
this,
web_response,
response_handler,
asio::placeholders::error,
asio::placeholders::bytes_transferred)
);
MatchResponseLine中对"\r\n"进行遍历,找到就返回相应的response_迭代器位置,然后读取完成后调用回调函数OnReadResopnseLineHandler
读取reponse header:
asio::async_read_until(socket_,
response_,
MatchResponseHeader,
bind(&HttpsWebClient::OnReadResponseHeaderHandler,
this,
web_response,
response_handler,
asio::placeholders::error,
asio::placeholders::bytes_transferred)
);
解析如上。
读取response body:
socket_.async_read_some(
asio::buffer(read_data_buffer_, READ_DATA_BUFFER_SIZE),
bind(&HttpsWebClient::OnReadResponseBodyHandler, this,
web_response,
response_handler,
asio::placeholders::error,
asio::placeholders::bytes_transferred)
这三次调用是顺序调用的,也就是在OnReadResponseLineHandler中调用了read response header, 然后在OnReadResonseHeaderHandler中调用了read reponse body.
然后就出现了问题,当读取reponse line和reponse body时就能够正常的拿到所有数据。但最后一步读取reponse body的时候就发现body的前120个字节不见了。
一开始以为是boost 的 asyn_read_some接口出问题了,上google查了下发现没有人有遇到类似的问题,但还是换了下接口,换成asyn_read,改了下相关的逻辑,发现没有办法解决问题。于是就开始怀疑是缓冲区的处理的问题,
使用单步调试进入MatchResponseHeader中,发现在read response header的时候就已经把body的一部分数据读到了response_缓冲区中了,而当我们去读body的时候,使用了另外一个缓冲区read_data_buffer_缓冲区,导致了body开头的数据丢失。
所以发现问题后,解决方法就是在read response body中也使用相同的response_缓冲区。
修改后的代码如下:
asio::async_read(socket_,
response_,
//asio::buffer(read_data_buffer_,
READ_DATA_BUFFER_SIZE),
boost::asio::transfer_at_least(1),
bind(&HttpsWebClient::OnReadResponseBodyHandler,
this,
web_response,
response_handler,
asio::placeholders::error,
asio::placeholders::bytes_transferred)
);
验证后证明是OK的。
相关文章推荐
- 【开源中国Android客户端】源码分析 网络数据传输接口
- 【开源中国Android客户端】源码分析(二)网络数据传输接口
- ArcGIS 网络分析[8.2] 资料2 使用IDatasetContainer2接口的CreateDataset方法创建网络数据集
- 网络库crash以及boost asio strand dispath分析
- boost asio异步读写网络聊天程序client 实例具体解释
- LR:接口性能测试中的应用服务器监控数据指标分析(Linx内存管理 和 性能学习)
- boost::asio async_write也不能保证一次发完所有数据 一
- boost::asio使用async_read_until配合boost::regex读取数据
- Boost.Asio c++ 网络编程翻译(1)
- 网络附加存储设备NAS等设备应用在数据备份(本地及远程数据备份)、数据容灾应用中的分析
- Python网络爬虫实战:根据天猫胸罩销售数据分析中国女性胸部大小分布
- Jpcap JAVA捕捉并分析网络数据包
- Boost::asio io_service 实现分析
- Boost.Asio c++ 网络编程翻译(28)
- Boost::asio范例分析 服务端线程池实现
- 《网络爬虫-Python和数据分析》数据库建库建表问题
- boost::asio范例分析
- WireShark使用lua接口截获网络数据
- vlc学习计划(5)--网络数据流接收处理过程分析
- 网络数据分析利器Wireshark