У меня проблема в программировании сокетов с 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 решения:
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);
Мое первое предположение состоит в том, что вы заставляете ASIO блокировать ожидание полного ввода-вывода для завершения. Это вводит задержку.
Для кода, чувствительного к задержке, вы всегда должны использовать async_read_some()
а также async_write_some()
, Они вернут как можно скорее любой частичный ввод / вывод, поэтому вы завершите столько, сколько может сделать ОС, как только она сможет это сделать. Вам, конечно, потребуется реорганизовать свой код для обработки частичного ввода-вывода, в основном обрабатывая столько, сколько вы можете на каждый вызов обработчика, и держите вокруг любой буферной последовательности любые необработанные частично отправленные или полученные буферы для повторной попытки в следующий раз, пока они не будут израсходованы.
Мое второе предположение, что вы можете использовать пряди. Они вводят латентность. Смотрите список рассылки asio-users.
Спасибо за помощь. Я нашел ответ — Я использую отладочную версию для запуска …
но что-то все еще странно.
Сначала я разрабатываю в режиме отладки. После завершения разработки, я переключаюсь в режим релиза и использую «Build Solution» для сборки моей dll. Я думал, что dll сейчас является релизной версией, поэтому я начал оценивать производительность. Но сегодня утром я не собираюсь использовать «Чистое решение», а затем «Построить решение». После сборки я снова оценил производительность и обнаружил, что почти вся задержка составляет 10 мс. Я предполагаю, что оценка до этого утра сделана dll с отладочной версией.
Я до сих пор не имею понятия о разнице между «переключением с отладки на выпуск и сборку решения» и «переключением с отладки на выпуск и очистку решения, а затем построение решения».
Я постараюсь выяснить разницу.
Очень ценю за помощь.