我是使用boost.asio的新手,但我想设计一个简单的例程来从URL获取数据并将其保存到内存缓冲区。根据我发现的一个例子,我想出了以下内容:
//data_url.hpp
#include <boost/asio.hpp>
#include <string>
#include <vector>
struct data {
data();
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver;
boost::asio::ip::tcp::socket socket;
std::vector<char> buffer;
std::string host;
std::string path;
std::string port;
};
void setup_url(std::string hst,
std::string pth,
std::string prt = "80");
std::vector<char> & get_data_from_url();
void resolve_handler(const boost::system::error_code & ec,
boost::asio::ip::tcp::resolver::iterator it);
void connect_handler(const boost::system::error_code & ec);
void read_handler(const boost::system::error_code & ec,
std::size_t bytes_transferred);
实施
//data_url.cpp
#include <data_url.hpp>
#include <iostream>
data::data() : io_service(), resolver(io_service), socket(io_service)
, buffer(), host(), path(), port() {}
data d;
void setup_url(std::string hst, std::string pth, std::string prt) {
d.host = hst;
d.path = pth;
d.port = prt;
}
std::vector<char> & get_data_from_url() {
boost::asio::ip::tcp::resolver::query query(d.host, d.port);
d.resolver.async_resolve(query, resolve_handler);
d.io_service.run();
return d.buffer;
}
void resolve_handler(const boost::system::error_code & ec,
boost::asio::ip::tcp::resolver::iterator it) {
if( !ec ) {
d.socket.async_connect(*it, connect_handler);
}
}
void connect_handler(const boost::system::error_code & ec) {
if( !ec ) {
boost::asio::write(d.socket,
boost::asio::buffer(std::string("GET ") +
std::string(d.path) +
std::string(" HTTP 1.1\r\n") +
std::string("Host: ") +
std::string(d.host) +
std::string("\r\n\r\n")));
boost::system::error_code ec_avail;
d.buffer.resize(d.socket.available(ec_avail));
d.socket.async_read_some(boost::asio::buffer(d.buffer),
read_handler);
}
}
void read_handler(const boost::system::error_code & ec,
std::size_t bytes_transferred) {
if( !ec ) {
d.socket.async_read_some(boost::asio::buffer(d.buffer),
read_handler);
}
}
然后我用
运行它#include <data_url.hpp>
int main(int argc, char *argv[]) {
setup_url("www.boost.org", "/");
std::vector<char> data;
data = get_data_from_url();
return 0;
}
代码无休止地调用read_handler并且永远不会终止。我已尝试过不同的页面,这没有什么区别。
此外,在content_handler
函数中,我使用socket.available()
调整向量的大小。这是为了使代码尽可能通用,这样我就可以阅读任何页面而无需知道它的大小。但是,当我调用socket.available()
时,它返回零并将ec_avail
中的错误代码设置为“未定义的错误”。
正如我所提到的,我是使用boost.asio的新手,显然我在这里遗漏了一些东西。我很感激帮助解决这些错误以及任何其他建议/建议。
答案 0 :(得分:3)
调用write后,套接字不太可能立即提供数据,因此调整大小的方法可能不起作用,然后使用大小为0的缓冲区调用async_read_some。
async_read_some的重点在于它不需要在异步操作完成之前填充整个缓冲区,因此使用基本块大小为8192的临时缓冲区,并在每次成功调用读取处理程序后,将读取的数据附加到主缓冲区的末尾。
ASIO不是一个HTTP库,所以如果你用它来通过HTTP下载文件,你需要动态地处理大量的数据来解析标题并确定它的响应类型是,确定内容长度和编码等。
如果您只是想将它用于HTTP内容,我强烈建议您使用Poco,因为它内置了对HTTP流的支持。