2020年11月29日日曜日

cpprestsdkでHTTP通信に失敗

お久しぶりです。ひっくです。

C++でWebAPIと通信する機能を作成した際、環境要因で(?)
WebAPIからのレスポンスを受信できないという現象があり、
解決に手間取ったので、方法を備忘録として残しておきます。

前提条件


 ・C++でHTTP(S)通信を行うため、Microsoft提供のcpprestsdkを使用

 ・cpprestsdkのDLLはNuGetで取得(version:2.5.0)

 ・WindowsXP(Embedded)で発生(ただし1回目の通信は成功し、2回目以降で失敗)

発生した現象について



実装していたコードはざっくり記載するとこんな感じです。
http_client_config cfg;
http_client client(L"URL文字列", cfg)

auto request = client.request(method::Post, L"", postData.serialize(), L"application/json");
request.then([](http_response response)
{
    // 受信時の処理(ローカル変数に受信時のJSON文字列を保持)
}.wait();
このコード、Windows10(64bit)では問題なく動作しました。
しかし問題となっている環境(WindowsXP)では、何故か受信しないように見えるパターンが存在しました。

Wiresharkを入れて通信を監視してみましたが、クライアント - WebAPI間ではHTTPレスポンスも
受信できており、直前・直後のTCP通信も正常のため、何故??という状態になりました。

対処法



WebAPIからのレスポンス待機を行う部分について、別の書き方ができるか調べてみた結果
以下に変更するとうまくいきました。

変更前
request.then([](http_response response)
{
    // 受信時の処理(ローカル変数に受信時のJSON文字列を保持)
}.wait();

変更後
// ここでリクエスト送信+レスポンス待機
auto resp = request.get();
// 待機完了後、レスポンスのJSON文字列を取得
auto respJson = resp.extract_json().get();
get() 内部でレスポンス待機処理が記載されており、
問題が発生したコードと機能の実装は変わらないと言えます。

内部処理のため直接原因は分からないままでしたが、「http_client.request」が
タスクチェーンで「wait」「then」の組み合わせとなった場合に、問題の現象が発生するのかもしれません。

なお、別の書き方として以下の様な方法もありました。
while(!request.is_done())
{
    // 待機処理
}

こちらのコードも問題の現象は発生しなくなりますが、「request.is_done()」が完了済みと
判断する時点が分からないため、不要な通信が発生する可能性があるという点で、
使用は控えるべきかと思います。

今回はこのへんで。ではまた!

0 件のコメント:

コメントを投稿