1

私はcasablanca cpprestskdでクライアントサーバーアプリケーションを開発しました。 5分ごとに、クライアントは自分のタスクマネージャ(プロセス、CPU使用状況など)からPOSTメソッドを介してサーバーに情報を送信します。http_listener cpprestsdk複数の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; 

} 

基本的に、それは動作しますが、私は同じ時間に起因するクライアントからの情報を送信しようとした場合、時にはそれが時にはそれが仕事をdoen't動作します。 明らかに私が "uploaded.txt"ストリームファイルを開くときの問題。 質問:

1)CASABLANCA http_listenerは本当にマルチタスクですか?何個のタスクを処理できるのですか? 2)私のドキュメントに似ていませんでしたが、鉱山に近づいているのは "Casalence120"プロジェクトですが、Concurrency :: Reader_writer_lockクラス(mutexメソッドのようです)を使用しています。 複数のPOSTを管理するにはどうすればよいですか? 3)uploaded.txtを開く前にクライアント情報を読むことはできますか? 出力ファイルストリームを直接クライアントの名前で開くことができました。 4)私がuploaded.txtファイルのmutex経由でアクセスをロックすると、Serverはシーケンシャルになり、これはcpprestsdkを使う良い方法ではないと思います。 私はまだcpprestskdに近づいていますので、どんな提案も役に立ちます。

答えて

1
  1. はい、REST SDKのプロセスが別のスレッド
  2. 上のすべての要求は、私は、リスナーを使用して多くの例が存在しないことを確認します。 リスナーを使用した公式のサンプルは、ここにあります: https://github.com/Microsoft/cpprestsdk/blob/master/Release/samples/CasaLens/casalens.cpp
  3. 私はあなたがVSで働いているのを見ています。最新のコンパイラがコルーチンをサポートしているので、VC++ 2015以上のVC++ 2017に移行することを強くお勧めします。 co_awaitを使用すると、コードの可読性が大幅に簡素化されます。 関数を実行するたびにコンパイラはコードを "継続"でリファクタリングし、関数自体を実行するスレッドをフリーズさせないようにします。このようにして、 ".then"ステートメントを取り除くことができます。
  4. ファイルの問題は、REST SDKとは異なる話です。ファイルシステムへの同時アクセスは、別のプロジェクトでテストする必要があります。毎回ディスクにアクセスするのではなく、最初の読み取りをキャッシュして、他のスレッドでコンテンツを共有することができます。
+0

"uploaded.txt"ストリームファイルを開いたときに他のクライアントと情報を共有する必要はありません。クライアントログインとパスワードを読み取る必要があり、コピーする必要がある一時ファイルですクライアントと同じ名前のファイルに保存します。毎回違う名前のストリームファイルを開く機会はありますか?私はそのように解決することができました! – kenhero

+0

最後のリクエストで混乱します。もちろん、ストリームファイルを別の名前で開くチャンスはありますが、非同期呼び出しの流れを理解することはあなた次第です。 おそらくコードはコルーチンを使用することで簡略化されるでしょう。デバッグ時に「then」を使用して継続することは理解しにくい場合があります。 (私は質問を理解しましたか?) – raf

+1

すべてのクライアントに異なる名前のストリームファイルを開けて解決しました。私はJmeterでテストを強調し、Serverは複数のクライアント要求を管理することができます。 機能ユニットテストでテストを終了した後、コルーチンを使ってメソッドを変更しようとします。ありがとう – kenhero

関連する問題