c++ - 通过 boost asio iostream 下载大文件的最快方法是什么?
问题描述
我正在尝试通过 boost::asio::ip::tcp::iostream 下载/传输一个大文件,例如:
boost::asio::ip::tcp::iostream stream("127.0.0.1", "1234");
stream << "GET /data HTTP/1.0\r\n\r\n" << std::flush;
std::string text;
while (std::getline(stream, text)) {
// pass, no operation here
}
但是,代码在我的本地机器上下载一个 400MB 的文件需要超过 3 秒的时间,这对于localhost文件传输来说太慢了。谁能给我任何关于如何加快速度的建议?
解决方案
如果你真的(?)想要 /dev/null 数据,这里有一个 hack:
boost::asio::ip::tcp::iostream stream("127.0.0.1", "1234");
stream << "GET /data HTTP/1.0\r\n\r\n" << std::flush;
std::ostream ons(nullptr);
ons << stream.rdbuf();
如果您真的想下载文件,请阅读标题:
for (std::string text; std::getline(stream, text);)
if (text.empty())
break; // end of headers
然后逐块读取正文:
char buf[2048];
while (stream.read(buf, sizeof(buf)) || stream.gcount()) {
// do something with gcount() bytes in buf?
}
高级 HTTP 意识
当然,HTTP 是一个善变的野兽。它可以使用压缩、分块编码、保持活动等。这很容易导致您读取损坏的正文。为了更安全,请使用 Beast 做家务:
int main() {
net::io_context io;
tcp::socket s(io);
s.connect({{}, 1234});
std::string const& req = "GET /data HTTP/1.0\r\n\r\n";
net::write(s, net::buffer(req));
http::request<http::string_body> response;
beast::flat_buffer buf;
http::read(s, buf, response);
}
为了更加了解,为什么不以相同的方式编写/发送请求:
{
http::request<http::empty_body> req;
req.method(http::verb::get);
req.target("/data");
req.version(10);
http::write(s, req);
}
完整列表
#include <boost/beast.hpp>
#include <boost/beast/http.hpp>
namespace net = boost::asio;
namespace beast = boost::beast;
namespace http = beast::http;
using net::ip::tcp;
int main() {
net::io_context io;
tcp::socket s(io);
s.connect({{}, 1234});
{
http::request<http::empty_body> req;
req.method(http::verb::get);
req.target("/data");
req.version(10);
http::write(s, req);
}
{
http::request<http::string_body> response;
beast::flat_buffer buf;
http::read(s, buf, response);
}
}