gsop を介して https ベースの Web サービス インターフェイスを呼び出す C++ の概要

ww 手順:

ステップ 1: ヘッダー ファイルを生成する

Web サービス インターフェイスには通常、外部インターフェイス ドキュメントがあります。例: http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL

疑問符の後のパラメータは、XML ドキュメントである WSDL ドキュメントを表します。構成を理解していなくても問題ありません。次に、このドキュメントを通じて C++ ヘッダー ファイルを生成する必要があります。

(1) gsoapツールのダウンロード

ダウンロード リンク: gSOAP ツールキットのダウンロード | SourceForge.net

 ダウンロードが完了したら、解凍して gsoap\bin\win32 ディレクトリに移動します。このディレクトリには、wsdl2h.exe とsoapcpp2.exe という 2 つのファイルがあります。wsdl2h.exe はヘッダー ファイルの生成に使用されます。ヘッダー ファイルを生成するだけでは十分ではないため、現時点では、soapcpp2.exe を使用して、プロジェクト内での呼び出しに使用できる対応する C++ ファイル構造を生成する必要があります (2 番目の手順で説明します)。まずはヘッダファイルの生成方法を見てみましょう。

 gsoap\bin\win32 ディレクトリで cmd コマンドを開きます。入力:

wsdl2h.exe -o head.h http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL

 実行が完了すると、現在のディレクトリに追加のヘッダー ファイル head.h があることがわかります。開いて見てみると、中にはいくつかのインターフェース機能があります。

 注: Web サービスは、送信プロセス中にデフォルトで UTF-8 エンコーディングを使用します。もちろん、gsoap はヘッダー ファイルの生成時にデフォルトでナロー文字も使用します。string や char* など。このとき、再度呼び出し時にパラメータに漢字が含まれていると文字化けしてしまいます。解決策は 2 つあります。

方法 1: 後で呼び出すときにコードに文を追加します (追加する具体的な場所は後で紹介します)。

soap_set_mode(&m_soap, SOAP_C_UTFSTRING);

 方法 2: デフォルトでは、ルート ディレクトリにある typemap.dat を使用してナロー文字にコンパイルします。現時点では適用しませんが、現在のディレクトリに新しい mytypemap.dat を作成します。内容は次のとおりです: xsd__string = | std::wstring | wchar_t*。その後、cmd コマンドを再実行します。

wdsl2h.exe -o head.h -t mytypemap.dat http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL

 再生成後、head.h の文字列型が wchar_t * または wstring 型に変更されたことがわかります。

ステップ 2: 呼び出し可能な API を生成する

現在のディレクトリで cmd コマンドを実行します。

soapcpp2.exe -C -x -I ..\..\import head.h

  

このうち -C はクライアントコードのみを生成します。-x は XML を生成しないことを意味します (C++ コードのみが必要です) -I はインポート ディレクトリを指定することを意味します。
実行が成功すると、現在のディレクトリにさらにいくつかのファイルが存在します。

 ステップ 3: プロジェクトにインポートする
上の図の赤いボックス内のファイルをプロジェクトに追加します。さらに 2 つのファイルを追加する必要があります。gsoap ルート ディレクトリ内の stdsoap2.h および stdsoap2.cpp もプロジェクトに追加する必要があります。
追加した 3 つの cpp ファイルを右クリックし、[プロパティ] -> [すべての構成] -> [c/c+±]> [プリコンパイル済みヘッダー] を選択し、プリコンパイル済みヘッダーを使用しないことを選択します。以下に示すように。

構成が完了したら、コードの記述を開始できます。

ステップ 4: コードを書く

「soapTest」という名前の新しい MFC ベースのアプリケーション プロジェクトを作成します。 

新しいsoapTestDlg.cppを作成し、ヘッダーファイルを導入します

#include "WeatherWebServiceSoap.nsmap"
#include "soap.h"

プロジェクト内でこれら 2 つのヘッダー ファイルを参照すると、コンパイルで異常なエラーが報告されました。よく確認してみると、すべて定義が重複していることがわかりました。ヘッダー ファイルWeatherWebServiceSoap.nsmapの名前空間が、プロジェクト内の元のソケット ライブラリと競合しているためです。解決策は、先頭に#include "WeatherWebServiceSoap.nsmap"を記述することです。プリコンパイル済みヘッダーを使用する場合は、 stdafx.hファイルに記述するのが最適ですヘッダー ファイルを導入した後、再度コンパイルしてもエラーは報告されません。プリコンパイル済みヘッダーを追加しない場合は、soapC.cpp、soapClientLib.cpp、soapClient.cpp、および stdsoap2.cpp をプリコンパイル済みヘッダーを使用しないように設定する必要があります。


サービスのすべてのインターフェイスは、soapClient.cpp で確認できます。関数名の形式は、soap_call __ns1_XXX です。
まず、SOAP オブジェクトを作成し、初期化します。

struct soap m_soap;
//SOAP初始化
soap_init(&m_soap);
soap_set_mode(&m_oSoap, SOAP_C_UTFSTRING);

これはsoap_set_mode(&m_oSoap, SOAP_C_UTFSTRING);まさに最初に漢字に適応すると言われていたことです。wstring または wchar_t * が最初に使用された場合は、無視できます。次に、reqXml 文字列を定義し、インターフェイス関数を呼び出します。XML 文字列内の二重引用符はエスケープする必要があります。

char* _reqXml = "<root>.....</root>";
char* _Return;
soap_call_ns1__XXX(&m_soap, NULL, NULL, G2U(_reqXml), _Return);
string ret = U2G(_Return);

上記のコードはパラメータとしてナロー文字、つまり char * を使用しているため、UTF-8 形式に変換する必要があります。具体的な機能は以下の通りです。

char* U2G(const char* utf8)
{
	int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
	wchar_t* wstr = new wchar_t[len + 1];
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
	len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = new char[len + 1];
	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
	if (wstr) delete[] wstr;
	return str;
}

char* G2U(const char* gb2312)
{
	int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
	wchar_t* wstr = new wchar_t[len + 1];
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
	len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = new char[len + 1];
	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
	if (wstr) delete[] wstr;
	return str;
}

この時点でコンパイルは成功するはずです。しかし、現実は残酷です。返される _Return 値は NULL で、何か問題があったことを示します。私のアドレスは https です。http を使用して直接リクエストすると、301 が返されます。検索情報には、301 はリダイレクトを意味するとあります。つまり、ブラウザのようにアドレス バーに http を入力することはできず、ブラウザは https にリダイレクトします。 。この時点では、まだ https に変更する必要があります。再度コンパイルします。うーん、まだエラーが報告されています。エラーコードはデバッグ時にm_soap構造体のerrorフィールドの値を確認することができ、常に0であれば問題がないことを意味します。特定のエラー コードをオンラインで確認できます。
https に変更してデバッグすると、m_soap->error の値が 30 であることがわかります。ドキュメントを確認すると、30 は SSL セキュリティ認証が実行されないことを意味していることがわかります。さて、
soap_init(&m_soap) の後に次のコードを追加します。

soap_ssl_init();
if (soap_ssl_server_context(&m_soap, SOAP_SSL_NO_AUTHENTICATION, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
	soap_print_fault(&m_soap, stderr);
	exit(-1);
}

soap_ssl_server_context パラメータに SSL 証明書がある場合は、パスワードを入力します。全部NULLでなくても大丈夫です。
再度コンパイルした後も、~ でコードをチェックできず、stdsoap2.hヘッダー ファイルにWITH_OPENSSLが定義されていないことがわかりました。下は灰色です。

 解決策: プロジェクトのプロパティを右クリックし、[C/C+±] > [プリプロセッサ] > [プリプロセッサ定義にWITH_OPENSSLを追加] を選択します。

 付けてみると、グレー色が消えているのが分かりました。

soap_ssl_server_contextコンパイル後、関数で解決できない外部シンボルの エラーが再度報告されます。

理由

        この関数の実装は定義されていません。opensslライブラリを導入するのを忘れていました。ダウンロードアドレス: https://slproweb.com/products/Win32OpenSSL.html

ダウンロード完了、インストール、インストール完了ディレクトリ。

 次に、vs でプロジェクトを右クリックし、[プロパティ] -> [構成プロパティ] -> 以下に示すように、VC++ ディレクトリにインクルード ディレクトリとライブラリ ディレクトリを追加します。

 以下に示すように、vs でプロジェクトを右クリックし、[プロパティ] -> [構成プロパティ] -> [ライブラリをリンク] -> [入力] -> libcrypto.lib と libssl.lib を追加の依存ライブラリ項目に追加します。

ファイル構造

 知らせ:

以下に示すように、soapClient.obj に xx が定義されているというエラーが報告された場合

 解決:

        すべてのsoapClientLib.cppをコメントアウトし、再度コンパイルします。

 以下は gsoap+opensll ツールです

https://download.csdn.net/download/my_angle2016/88220982

おすすめ

転載: blog.csdn.net/my_angle2016/article/details/132302759