?? soapdoc2.html
字號:
// Content of file <tt>"getQuote.h"</tt>: <br />
<b>int</b> ns1__getQuote(<b>char</b> *symbol, <b>float</b> &Result);
</td></tr></table><br></i>
The header file essentially specifies the remote method in C++.
The remote method is declared as a <i>ns1__getQuote</i> <b>function prototype</b> which specifies all of the necessary details for
the gSOAP compiler to generate the stub routine for a client application to interact with the Delayed Stock Quote service.
<p>The Delayed Stock Quote service description requires that the <b>input parameter</b> of the <i>getQuote</i> remote method is a
<i>symbol</i> parameter of type string. The description also indicates that the <i>Result</i> <b>output parameter</b> is a floating
point number that represents the current unit price of the stock in dollars. The gSOAP compiler uses the convention the <b>last
parameter</b> of the function prototype must be the output parameter of the remote method, which is required to be passed by
reference using the reference operator (<i>&</i>) or by using a pointer type. All other parameters except the last are input
parameters of the remote method, which are required to be passed by value or passed using a pointer to a value (by reference is
not allowed). The function prototype associated with a remote method is required to return an <i><b>int</b></i>, whose value indicates to
the caller whether the connection to a SOAP Web service was successful or resulted in an exception, see Section <a href="#sec:errcodes">7.2</a>
for the error codes.
<p>The use of the namespace prefix <i>ns1__</i> in the remote method name in the function prototype declaration is discussed in
detail in <a href="#sec:namespace">5.1.2</a>. Basically, a namespace prefix is distinghuished by a <b>pair of underscores</b> in the function
name, as in <i>ns1__getQuote</i> where <i>ns1</i> is the namespace prefix and <i>getQuote</i> is the remote method name. (A single
underscore in an identifier name will be translated to a dash in the XML output, see Section <a href="#sec:idtrans">7.3</a>.)
<p>The gSOAP compiler is invoked from the command line with:
<br><br><table border=0 width="100%" cellpadding="8" bgcolor="#D0D0D0"><tr><td><span class="roman">
<i>soapcpp2 getQuote.h</i>
</td></tr></table><br></span>
The compiler generates the stub routine for the <i>getQuote</i> remote method specified in the <i>getQuote.h</i> header file. This
stub routine can be called by a client program at any time to request a stock quote from the Delayed Stock Quote service. The
interface to the generated stub routine is called a <b>proxy</b>, which is the following function generated by the gSOAP
compiler:
<br><br><table border=0 width="100%" cellpadding="8" bgcolor="#B0D0B0"><tr><td><i>
<b>int</b> soap_call_ns1__getQuote(<b>struct</b> soap *soap, <b>char</b> *URL, <b>char</b> *action, <b>char</b> *symbol, <b>float</b> &Result);
</td></tr></table><br></i>
The stub routine of the proxy is saved in <i>soapClient.cpp</i>. The file <i>soapC.cpp</i> contains the <b>serializer</b> and <b>
deserializer</b> routines for the data types used by the stub.
<p>Note that the parameters of the <i>soap_call_ns1__getQuote</i> proxy are identical to the
<i>ns1__getQuote</i> function prototype with three additional input parameters: <i>soap</i> must be a valid pointer to a gSOAP
runtime environment, <i>URL</i> is the SOAP Web service <b>endpoint URL</b>
passed as a string, and <i>action</i> is a string that denotes the <b>SOAP action</b> required by the Web service.
<p>The following example C++ client program invokes the proxy to retrieve the latest AOL stock quote from the XMethods Delayed Stock
Quote service:
<br><br><table border=0 width="100%" cellpadding="8" bgcolor="#B0D0B0"><tr><td><i>
#include <tt>"soapH.h"</tt> // obtain the generated proxy <br />
<b>int</b> main() <br />
{ <br />
<b>struct</b> soap soap; // gSOAP runtime environment <br />
<b>float</b> quote; <br />
soap_init(&soap); // initialize runtime environment (only once) <br />
<b>if</b> (soap_call_ns1__getQuote(&soap, <tt>"http://services.xmethods.net:80/soap"</tt>, <tt>""</tt>, <tt>"AOL"</tt>, quote) == SOAP_OK) <br />
cout << "Current AOL Stock Quote = " << quote; <br />
<b>else</b> // an error occurred <br />
soap_print_fault(&soap, stderr); // display the SOAP fault message on the stderr stream <br />
soap_end(&soap); // clean up <br />
}
</td></tr></table><br></i>
The XMethods Delayed Stock Quote service endpoint URL is <tt>http://services.xmethods.net/soap</tt> port 80 and the SOAP action required
is <tt>""</tt> (two quotes). If successful, the proxy returns <i>SOAP_OK</i> and <i>quote</i> contains the latest stock quote.
Otherwise, an error occurred and the SOAP fault is displayed with the <i>soap_print_fault</i> function.
<p><p>When the example client application is invoked, the SOAP request is performed by the proxy routine <i>soap_call_ns1__getQuote</i>, which
generates the following SOAP request message:
<br><br><table border=0 width="100%" cellpadding="8" bgcolor="#B0B0D0"><tr><td><tt>
POST /soap HTTP/1.1 <br />
Host: services.xmethods.net <br />
Content-Type: text/xml <br />
Content-Length: 529 <br />
SOAPAction: "" <br />
<br />
<?xml version="1.0" encoding="UTF-8"?> <br />
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" <br />
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" <br />
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" <br />
xmlns:xsd="http://www.w3.org/1999/XMLSchema" <br />
xmlns:ns1="urn:xmethods-delayed-quotes" <br />
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <br />
<SOAP-ENV:Body> <br />
<ns1:getQuote> <br />
<symbol>AOL</symbol> <br />
</ns1:getQuote> <br />
</SOAP-ENV:Body> <br />
</SOAP-ENV:Envelope>
</td></tr></table><br></tt>
The XMethods Delayed Stock Quote service responds with the SOAP response message:
<br><br><table border=0 width="100%" cellpadding="8" bgcolor="#B0B0D0"><tr><td><tt>
HTTP/1.1 200 OK <br />
Date: Sat, 25 Aug 2001 19:28:59 GMT <br />
Content-Type: text/xml <br />
Server: Electric/1.0 <br />
Connection: Keep-Alive <br />
Content-Length: 491 <br />
<br />
<?xml version='1.0' encoding='UTF-8'?> <br />
<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' <br />
xmlns:xsi='http://www.w3.org/1999/XMLSchema-instance' <br />
xmlns:xsd='http://www.w3.org/1999/XMLSchema' <br />
xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/' <br />
soap:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'> <br />
<soap:Body> <br />
<n:getQuoteResponse xmlns:n='urn:xmethods-delayed-quotes'> <br />
<Result xsi:type='xsd:float'>41.81</Result> <br />
</n:getQuoteResponse> <br />
</soap:Body> <br />
</soap:Envelope>
</td></tr></table><br></tt>
The server's response is parsed by the stub routine of the proxy of the client. The stub routine further demarshalls the data of <tt>Result</tt>
element of the SOAP response and stores it in the <i>quote</i> parameter of <i>soap_call_ns1__getQuote</i>.
<p>A client program can invoke a remote method at any time and multiple times if necessary. Consider for example:
<br><br><table border=0 width="100%" cellpadding="8" bgcolor="#B0D0B0"><tr><td><i>
... <br />
<b>struct</b> soap soap; <br />
<b>float</b> quotes[3]; char *myportfolio[] = {<tt>"IBM"</tt>, <tt>"AOL"</tt>, <tt>"MSDN"</tt>}; <br />
soap_init(&soap); // need to initialize only once <br />
<b>for</b> (<b>int</b> i = 0; i < 3; i++) <br />
<b>if</b> (soap_call_ns1__getQuote(&soap, <tt>"http://services.xmethods.net:80/soap"</tt>, <tt>""</tt>, myportfolio[i], quotes[i]) != SOAP_OK) <br />
<b>break</b>; <br />
<b>if</b> (soap.error) // an error occurred <br />
soap_print_fault(&soap, stderr); <br />
soap_end(&soap); // clean up all deserialized data <br />
...
</td></tr></table><br></i>
This client composes an array of stock quotes by calling the <i>ns1__getQuote</i> proxy for each symbol in a portfolio array.
<p>This example demonstrated how easy it is to build a SOAP client with gSOAP once the details of a Web service are available
in the form of a WSDL document.
<p> <h4><a name="tth_sEc5.1.2">5.1.2</a> <font color="#0000FF">Namespace Considerations</font></h4><a name="sec:namespace"></a>
<p>The declaration of the <i>ns1__getQuote</i> function prototype (discussed in the previous section) uses the namespace prefix
<i>ns1__</i> of the remote method namespace, which is distinghuished by a <b>pair of underscores</b> in the function name to
separate the namespace prefix from the remote method name. The purpose of a namespace prefix is to associate a remote
method name with a service in order to prevent naming conflicts, e.g. to distinguish identical remote method names used
by different services.
<p>Note that the XML response of the XMethods Delayed Stock Quote service example uses the <b>namespace prefix</b> <tt>n</tt> which is
associated with the <b>namespace URI</b> <tt>urn:xmethods-delayed-quotes</tt> through the <tt>xmlns:n="urn:xmethods-delayed-quotes</tt>
binding. The use of namespace prefixes and namespace URIs is also required to enable SOAP applications to validate the content of
a client's request and vice versa. The namespace URI in the service response is verified by the stub routine by using the
information supplied in a <b>namespace mapping table</b> that is required to be part of the client program. The table is accessed
at run time to resolve namespace bindings, both by the generated stub's data structure serializer for encoding the client request
and by the generated stub's data structure deserializer to decode and validate the service response. The namespace mapping table
should not be part of the header file input to the gSOAP stub and skeleton compiler.
<p>The namespace mapping table for the Delayed Stock Quote client is:
<br><br><table border=0 width="100%" cellpadding="8" bgcolor="#B0D0B0"><tr><td><i>
<b>struct</b> Namespace namespaces[] = <br />
{ // {"ns-prefix", "ns-name"} <br />
{<font color="#FF0000">"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"</font>}, // MUST be first <br />
{<font color="#0000FF">"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"</font>}, // MUST be second <br />
{<font color="#FF00FF">"xsi", "http://www.w3.org/2001/XMLSchema-instance"</font>}, // MUST be third <br />
{<font color="#00FFFF">"xsd", "http://www.w3.org/2001/XMLSchema"</font>}, // 2001 XML schema <br />
{<font color="#00FF00">"ns1", "urn:xmethods-delayed-quotes"</font>}, // given by the service description <br />
{NULL, NULL} // end of table <br />
};
</td></tr></table><br></i>
The first four namespace entries in the table consist of the standard namespaces used by the SOAP 1.1 protocol. In fact, the
namespace mapping table is explicitly declared to enable a programmer to specify the SOAP encoding style and to allow the
inclusion of namespace-prefix with namespace-name bindings to comply to the namespace requirements of a specific SOAP service. For
example, the namespace prefix <tt>ns1</tt>, which is bound to <tt>urn:xmethods-delayed-quotes</tt> by the namespace mapping table shown
above, is used by the generated stub routine to encode the <i>getQuote</i> request. This is performed automatically by the gSOAP
compiler by using the <i>ns1</i> prefix of the <i>ns1__getQuote</i> method name specified in the <i>getQuote.h</i> header file. In
general, if a function name of a remote method, <i><b>struct</b></i> name, <i><b>class</b></i> name, <i><b>enum</b></i> name, or field name of a
<i><b>struct</b></i> or <i><b>class</b></i> has a pair of underscores, the name has a namespace prefix that must be defined in the namespace
mapping table.
<p>The namespace mapping table will be output as part of the SOAP Envelope by the stub routine. For example:
<br><br><table border=0 width="100%" cellpadding="8" bgcolor="#B0B0D0"><tr><td><tt>
... <br />
<SOAP-ENV:Envelope xmlns:<font color="#FF0000">SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"</font> <br />
xmlns:<font color="#0000FF">SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"</font> <br />
xmlns:<font color="#FF00FF">xsi="http://www.w3.org/1999/XMLSchema-instance"</font> <br />
xmlns:<font color="#00FFFF">xsd="http://www.w3.org/1999/XMLSchema"</font> <br />
xmlns:<font color="#00FF00">ns1="urn:xmethods-delayed-quotes"</font> <br />
SOAP-ENV:encodingStyle=<font color="#0000FF">"http://schemas.xmlsoap.org/soap/encoding/"</font>> <br />
...
</td></tr></table><br></tt>
The namespace bindings will be used by a SOAP service to validate the SOAP request.
<p> <h4><a name="tth_sEc5.1.3">5.1.3</a> <font color="#0000FF">Example</font></h4><a name="sec:example2"></a>
<p>The incorporation of namespace prefixes into C++ identifier names is necessary to distinguish remote methods that
share the same name but are implemented in different Web services. Consider for example:
<br><br><table border=0 width="100%" cellpadding="8" bgcolor="#B0D0B0"><tr><td><i>
// Contents of file "getQuote.h": <br />
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -