ChrisB91 Ответов: 1

Отправка больших файлов с помощью boost::asio


Привет,

Я пытаюсь отправить большие файлы (~4 ГБ) с http-сервера некоторым клиентам. Моя реализация сервера основана на примере Boosts HTTPServer3 HTTPServer3.
Проблема в том, что файлы сначала полностью загружаются в память, а затем отправляются клиенту.
Я хотел бы прочитать куски размером около 5-10 МБ и отправить их перед чтением следующего куска, вместо того чтобы читать весь файл в одну строку (rep.content).

Вот как выглядит мой код:

// Open the file to send back.
std::ifstream is(full_path_no_params.c_str(), std::ios::in | std::ios::binary);
if (!is)
{
    rep = reply::stock_reply(reply::not_found);
    std::cout << "File not found\n";
    return;
}
// Fill out the reply to be sent to the client.
rep.status = reply::ok;
// add content of file to reply
char buf[512];
while (is.read(buf, sizeof(buf)).gcount() > 0)
    rep.content.append(buf, is.gcount());
rep.headers.resize(2);
rep.headers[0].name = "Content-Length";
rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size());
rep.headers[1].name = "Content-Type";
rep.headers[1].value = mime_types::extension_to_type(extension);


Данные отправляются с помощью boost::asio::async_write

boost::asio::async_write(socket_, reply_.to_buffers(),strand_.wrap(
    boost::bind(&connection::handle_write, shared_from_this(),
    boost::asio::placeholders::error)));


и определение reply_.to_buffers()

std::vector<boost::asio::const_buffer> reply::to_buffers()
{
    std::vector<boost::asio::const_buffer> buffers;
    buffers.push_back(status_strings::to_buffer(status));
    for (std::size_t i = 0; i < headers.size(); ++i)
    {
        header& h = headers[i];
        buffers.push_back(boost::asio::buffer(h.name));
        buffers.push_back(boost::asio::buffer(misc_strings::name_value_separator));
        buffers.push_back(boost::asio::buffer(h.value));
        buffers.push_back(boost::asio::buffer(misc_strings::crlf));
    }
    buffers.push_back(boost::asio::buffer(misc_strings::crlf));
    buffers.push_back(boost::asio::buffer(content));
    return buffers;
}


Есть идеи, как это сделать??
Могу ли я использовать что-то вроде boost::asio::streambuf?

Здоровается Крис

1 Ответов

Рейтинг:
2

KarstenK

Взгляните на это ответ на stackoverflow.

Рассмотрите возможность разбиения данных на более мелкие фрагменты в сетевых пакетах, кратных размеру, чтобы минимизировать отправку полупустых пакетов. Кратные 1024 могут подходить лучше всего.