gSOAPを使用してWebサービスを作成する

何言ってるの?


古くて良いC ++では、SOAPサービスを実装する必要がある場合があります。 もちろん、真のプログラミング愛好家は自分でサーバーを書くことを急ぎますが、私は時間を無駄にせず、既製のライブラリを使用することを好みません。 今日は、C ++アプリケーションでgSOAPライブラリをサーバーとして使用するトピックについて(少しだけ)取り上げたいと思います。

ツールキット


私の話ではVisual Studio 2010 SP1を使用しますが、すぐに、gSOAPがWindowsだけでなく他のプラットフォームやコンパイラーでも正常に機能することを説明します。

ライブラリ自体は[http://www.cs.fsu.edu/~engelen/soap.html](v2.8.2を使用しました)からダウンロードできます。

問題の声明


プロトコルに従って動作する支払い受付サービスを開発する必要があります(もちろん、私は嘘をついています)。
システムには、擬似署名を持つメソッドが1つしかありません。
void MakePayment([IN] int qty, [OUT]int& errorCode, [OUT]string& message)

行こう!


gSOAPでサーバーコードを生成するプロセスは、ほぼ完全に自動化されています。 Insideは、サービスを記述するための独自の言語を開発しました。文法は、「++」要素を持つCと非常に似ています。 そのため、 WSDLの学習であってもスチームバスを使用する必要はありません(ただし、それについては考えておく価値があります)。

さらに、信じられないほど幸運でした。なぜなら、 gSOAPディストリビューションには、Windowsを含む人気のあるプラットフォーム用のこの言語用のコンパイル済みプロセッサが既に含まれています(信じてください、あなたの手で(そしてWindows上でも)これをコンパイルすることは、オープンソースライブラリへの依存関係がたくさんあるため、あなたに喜びを与えそうにありません...

それで、gsoap \ bin \ win32 \ディレクトリに登って、そこに2つのプログラムを見ます。 soapcpp2.exeは、Cライクなサービス記述言語をサーバーコード、クライアントプロキシ(必要な場合)、wsdl記述、soap request-reply-envelopesの例に処理する、まさに必要なものを担当します。 近くにwsdl2h.exeがあります-このユーティリティを使用すると、サービスのWSDL記述を実行し、出力でsoapcpp2.exeでさらに使用するためにCのような言語でサービスの記述を取得できます。 最初のものだけが必要です。なぜなら WSDLのサービスの説明はまだありません。

-helpスイッチを使用して、各ユーティリティのマニュアルページを表示できます。 ここではすべてのオプションをリストしません。 デフォルトでは私たちに合ったものがたくさんあり、私が使用するオプションはヘルプからかなり明白です。

サーバー


サービスの説明から始めましょう。 通常は拡張子がhのファイルで生成されます。 ファイルにpaymentservice.hという名前を付け、その中に次のように記述します。
 //gsoap ns service name: paymentssl //gsoap ns service style: rpc //gsoap ns service encoding: encoded //gsoap ns service namespace: urn:paymentssl //gsoap ns service location: http://localhost:9999 //gsoap ns service method-action: MakePayment urn:MakePayment typedef int xsd__int; typedef char* xsd__string; enum t__status // remote status: { STATE_OK, // ok STATE_FAIL // fail to process }; class t__result { public: enum t__status errCode; xsd__string message; }; int ns__MakePayment(xsd__int qty, t__result* result); 


SOAPメッセージを直接処理するためのパラメーターは、「マジックコメント」(最初の行)の形式で設定されます。 それらにこだわることはほとんど意味がありません。 それらはほとんど標準SOAPのコピーです。 method-actionの形式を説明する価値がない場合-最初の引数はメソッドの名前を示し、2番目の適切なSOAPActionを示します。

soapcpp2.exe -2 -i -e paymentservice.hを起動しsoapcpp2.exe -2 -i -e paymentservice.h
パラメーターについて説明します。


その結果、多数のファイルが作成されます。 順番に並べましょう:


結果のWSDL記述は次のようになります。


サーバープログラミングを行うときです(サーバーの説明にはSSL文字列がありますが、暗号化については説明しません(ただし、サポートされています)。

プログラマブルサーバー


プリコンパイル済みヘッダーを使用しない空のコンソールアプリケーションを作成します。 そして、生成されたファイルをプロジェクトに追加します。

プロジェクトの形式は次のとおりです。


gSOAPカーネルファイルも追加されます: stdsoap2.cppおよびstdsoap2.h

私はすぐにPaymentServiceImplクラスを追加しました。 PaymentServiceImplクラスでは、サービスを実装する予定です。
すべてを収集するには、機能を決定する必要があります
 paymentsslService::MakePayment(int qty, t__result *result) 

これは仮想(ただし、純粋に仮想ではありません)であり、 PaymentServiceImpl実装PaymentServiceImpl paymentsslServiceから継承され、この操作をオーバーロードするため、どこかでスタブとして宣言する必要があります。
 // //implementation for generated code always return FAIL. //This method will be override in PaymentServiceImpl class // int paymentsslService::MakePayment(int qty, t__result *result) { return SOAP_ERR; } 

定数SOAP_ERR stdsoap2.h特にSOAP_ERR定義されています。

また、 PaymentServiceImplクラスにオーバーロードされたMakePayment関数の実装を追加します。

今度は、数値コードとテキストメッセージを使用して、操作の成功に関するメッセージを返すロジックをサービスに提供します。

次のロジックがあります。
1)qty <0の場合、SOAP例外をスローします(SOAP FAULT)
2)qty> 100の場合、「error」というメッセージとともにFAILエラーコードを返します
3)それ以外の場合、エラーコードをOKで、メッセージなしで返します

最終的な実装:
 // PaymentServiceImpl.h #pragma once #include "Autogenerated/soappaymentsslService.h" class PaymentServiceImpl : public paymentsslService { public: virtual int MakePayment(int qty, t__result *result); }; // PaymentServiceImpl.cpp #include "PaymentServiceImpl.h" #include "Autogenerated/paymentssl.nsmap" /*virtual*/ int PaymentServiceImpl::MakePayment(int qty, t__result *result) { this->mode = this->mode | SOAP_C_UTFSTRING; if(qty<0) { this->soap_senderfault("error!", "<error xmlns=\"http://tempuri.org/\">The input parameter must be positive</error>"); return SOAP_CLI_FAULT; } if(qty>100){ result->errCode = STATE_FAIL; char err[] = "error (2)!"; int len=strlen(err); result->message = reinterpret_cast<char*>(soap_malloc(this, len+1)); strcpy_s(result->message, len+1, err); result->message[len] = '\0'; } return SOAP_OK; } 


サービスを開始し、それが何かを提供するかどうかを確認する時が来ました。一般的には無駄になりました。
メインを入力:
 #include "PaymentServiceImpl.h" int _tmain(int argc, _TCHAR* argv[]) { const int SERVICE_PORT = 9999; std::auto_ptr<PaymentServiceImpl> srv (new PaymentServiceImpl()); if (srv->run(SERVICE_PORT)) { srv->soap_stream_fault(std::cerr); exit(-1); } return 0; } 


また、デバッグの目的で、プリプロセッサにDEBUGディレクティブを示します(スタジオは_DEBUGを設定します)。

検証の時間です。クライアントが必要です

私たちはクライアントを作ります


デモンストレーションのために、C#クライアントを簡単にスケッチします。これは非常に単純です(c ++ではより複雑ではありませんが、単一のプロトコル(SOAP自体が考えられていた)を使用して異なるツールの通信を示すC#の例を示します)。

新しいC#コンソールプロジェクトを追加してから、サービス参照を追加します。 アドレスとしてpaymentssl.wsdlファイルへのパスを示します。


プロジェクトのプロパティで、.NET4 Client Profileフレームワークではなく.Net4を使用していることを忘れないでください。

確認コードは次のとおりです。
 var proxy = new PaymentService.paymentsslPortTypeClient(); string msg; var errCode = proxy.MakePayment(out msg, 10); 

//
//はい、スタジオ(またはsvcutilユーティリティ)は、パラメーターがどうあるべきかについてかなり奇妙な理解を持っています。
//ただし、トピック「他のシステムおよびgSOAPとの相互作用」は、この紹介には十分な広さです。
//


生成されたapp.configも修正する必要があります。これで十分です。
 <configuration> <system.serviceModel> <bindings> <customBinding> <binding name="paymentssl"> <textMessageEncoding messageVersion="Soap12" /> <httpTransport/> </binding> </customBinding> </bindings> <client> <endpoint address="http://localhost:9999" binding="customBinding" bindingConfiguration="paymentssl" contract="PaymentService.paymentsslPortType" name="paymentssl"/> </client> </system.serviceModel> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup> </configuration> 

出来上がり、SOAPプロトコルを使用してサービスを呼び出す方法(自分で確認できます)を知っているクライアントもいます。

私が言わなかったこと




興味深い場合は、別の投稿(時間の表示方法)で説明します。
皆さん、SOAPをご利用いただきありがとうございます。

Source: https://habr.com/ru/post/J121853/


All Articles