首页 > 解决方案 > 通过 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文件传输来说太慢了。谁能给我任何关于如何加快速度的建议?

标签: c++boostboost-asio

解决方案


如果你真的(?)想要 /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);
    }
}

推荐阅读