http_listener cpprestsdk, как обрабатывать несколько запросов POST
Я разработал клиент-серверное приложение с помощью casablanca cpprestskd. Каждые 5 минут клиент отправляет информацию из своего диспетчера задач (процессы, использование процессора и т. Д.) На сервер методом POST.
Проект должен уметь управлять около 100 клиентами. Каждый раз, когда сервер получает запрос POST, он открывает поток выходных файлов ("uploaded.txt"), извлекает некоторую начальную информацию из клиента (логин, пароль), управляет этой информацией, сохраняет всю информацию в файле с тем же именем клиента (например: client1.txt, client2.txt) в режиме добавления и, наконец, ответ клиенту с кодом состояния. Это в основном мой код POST-дескриптора со стороны сервера:
void Server::handle_post(http_request request)
{
auto fileBuffer =
std::make_shared<Concurrency::streams::basic_ostream<uint8_t>>();
try
{
auto stream = concurrency::streams::fstream::open_ostream(
U("uploaded.txt"),
std::ios_base::out | std::ios_base::binary).then([request, fileBuffer](pplx::task<Concurrency::streams::basic_ostream<unsigned char>> Previous_task)
{
*fileBuffer = Previous_task.get();
try
{
request.body().read_to_end(fileBuffer->streambuf()).get();
}
catch (const exception&)
{
wcout << L"<exception>" << std::endl;
//return pplx::task_from_result();
}
//Previous_task.get().close();
}).then([=](pplx::task<void> Previous_task)
{
fileBuffer->close();
//Previous_task.get();
}).then([](task<void> previousTask)
{
// This continuation is run because it is value-based.
try
{
// The call to task::get rethrows the exception.
previousTask.get();
}
catch (const exception& e)
{
wcout << e.what() << endl;
}
});
//stream.get().close();
}
catch (const exception& e)
{
wcout << e.what() << endl;
}
ManageClient();
request.reply(status_codes::OK, U("Hello, World!")).then([](pplx::task<void> t) { handle_error(t); });
return;
}
В основном это работает, но если я пытаюсь отправить информацию от клиентов одновременно, иногда это работает, иногда это не работает. Очевидно, проблема, если, когда я открываю файл потока "uploaded.txt". Вопросы:
1) Является ли CASABLANCA http_listener реальной многозадачностью? Сколько задач она может выполнить? 2) Я не нашел в документации пример с топором, похожим на мой, единственный, кто подходит к моему, это проект "Casalence120", но он использует класс Concurrency::Reader_writer_lock (кажется, метод мьютекса). Что я могу сделать, чтобы управлять несколькими POST? 3) Можно ли прочитать информацию о клиенте, прежде чем открывать uploaded.txt? Я мог бы открыть выходной файл потока напрямую с именем клиента. 4) Если я блокирую доступ через мьютекс в файле uploaded.txt, сервер становится последовательным, и я думаю, что это не очень хороший способ использовать cpprestsdk. Я все еще подхожу к cpprestskd, поэтому любые предложения будут полезны.
1 ответ
- Да, REST SDK обрабатывает каждый запрос в другом потоке
- Я подтверждаю, что не так много примеров использования слушателя. Официальный пример с использованием слушателя можно найти здесь: https://github.com/Microsoft/cpprestsdk/blob/master/Release/samples/CasaLens/casalens.cpp
- Я вижу, вы работаете с VS. Я настоятельно рекомендую перейти на VC++2015 или лучше VC++2017, потому что самый последний компилятор поддерживает сопрограммы. Использование co_await значительно упрощает читабельность кода. Практически каждый раз, когда вы 'co_await' функция, компилятор будет рефакторинг кода в "продолжение", избегая наказания за замораживание потоков, выполняющих саму функцию. Таким образом, вы избавляетесь от утверждений ".then".
- Проблема с файлом - другая история, чем у REST SDK. Одновременный доступ к файловой системе - это то, что вы должны проверить в отдельном проекте. Вероятно, вы можете кэшировать первое чтение и делиться контентом с другими потоками, вместо того чтобы каждый раз обращаться к диску.