увеличить asio async_read delay (локальный сокет)

У меня проблема в программировании сокетов с boost asio.

Поток моей программы ниже:

Клиент использует async_write для отправки данных на сервер, затем он использует async_read для получения данных с сервера. Весь обработчик асинхронных операций — use_future, а время ожидания = 2 секунды.

Проблема в:

Время обработки сервера составляет около 10 мс. И сервер, и клиент находятся на одном компьютере, поэтому клиент должен получать данные, пока сервер их отправляет. Однако я измерил задержку async_read и обнаружил, что некоторые из них составляют около 10 мс, а другие — около 30–40 мс. Обычно они чередуются.

Как я измерил:

auto start_time = std::chrono::steady_clock::now();

auto read_result = async_read(..., use_future);
auto read_future_status = read_result.wait_for(timeout);

auto end_time = std::chrono::steady_clock::now();

Я пробовал 2 решения:

  1. Выделите больше места для boost :: asio :: streambuf. Я выделил 4096 байт, и мой размер данных никогда не превышает 1500 байт, но это не работает.
  2. использование socket_.set_option(ip::tcp::no_delay(true)); отключить алгоритм Nagle и задержка Ack. Кроме того, это не может работать.

Понятия не имею с проблемой. Кто-нибудь может мне помочь? Пожалуйста…

Обновления: вот части моего исходного кода

Ниже приведен код отправки запроса на сервер:

auto send_result = async_write(input_socket, out_buffer, use_future);
auto send_status = send_result.wait_for(std::chrono::seconds(timeout));
if(send_status == std::future_status::timeout)
{
LOG4CPLUS_ERROR_FMT(logger_, "send %s future error : (%d).", action, send_status);
}

out_buffer.consume(request.length());

Ниже приведен код получения данных с сервера.

auto read_buffer_result = async_read(output_socket, in_buffer, transfer_exactly(sizeof(Header)), use_future);
auto read_status = read_buffer_result.wait_for(std::chrono::seconds(timeout));
if(read_status == std::future_status::timeout)
{
LOG4CPLUS_ERROR_FMT(logger_, "read %s header future error : (%d).", action, read_status);
}
size_t byte_transferred = read_buffer_result.get();
in_buffer.consume(byte_transferred);

1

Решение

Мое первое предположение состоит в том, что вы заставляете ASIO блокировать ожидание полного ввода-вывода для завершения. Это вводит задержку.

Для кода, чувствительного к задержке, вы всегда должны использовать async_read_some() а также async_write_some(), Они вернут как можно скорее любой частичный ввод / вывод, поэтому вы завершите столько, сколько может сделать ОС, как только она сможет это сделать. Вам, конечно, потребуется реорганизовать свой код для обработки частичного ввода-вывода, в основном обрабатывая столько, сколько вы можете на каждый вызов обработчика, и держите вокруг любой буферной последовательности любые необработанные частично отправленные или полученные буферы для повторной попытки в следующий раз, пока они не будут израсходованы.

Мое второе предположение, что вы можете использовать пряди. Они вводят латентность. Смотрите список рассылки asio-users.

1

Другие решения

Спасибо за помощь. Я нашел ответ — Я использую отладочную версию для запуска …
но что-то все еще странно.

Сначала я разрабатываю в режиме отладки. После завершения разработки, я переключаюсь в режим релиза и использую «Build Solution» для сборки моей dll. Я думал, что dll сейчас является релизной версией, поэтому я начал оценивать производительность. Но сегодня утром я не собираюсь использовать «Чистое решение», а затем «Построить решение». После сборки я снова оценил производительность и обнаружил, что почти вся задержка составляет 10 мс. Я предполагаю, что оценка до этого утра сделана dll с отладочной версией.

Я до сих пор не имею понятия о разнице между «переключением с отладки на выпуск и сборку решения» и «переключением с отладки на выпуск и очистку решения, а затем построение решения».

Я постараюсь выяснить разницу.

Очень ценю за помощь.

1

По вопросам рекламы [email protected]