gSOAP服务端函数只能返回一个值,当然这个值可以是自定义类型(比如结构体,用来返回多个值),不过我在相关文档没有找到说明如何来做,查了一些论坛资料,终于解决,现总结如下:
1. 定义契约(服务)头文件,calc.h
// Contents of file "calc.h":
typedef double xsd__double;
typedef char *xsd__string;
class ns_student
{
public:
xsd__string name;
};
struct ns__getstudentResponse {ns_student return_;};
int ns__getstudent(struct ns__getstudentResponse &ret);
int ns__add(xsd__double a, xsd__double b, xsd__double &result);
int ns__sub(xsd__double a, xsd__double b, xsd__double &result);
int ns__sqrt(xsd__double a, xsd__double &result);
typedef double xsd__double;
typedef char *xsd__string;
class ns_student
{
public:
xsd__string name;
};
struct ns__getstudentResponse {ns_student return_;};
int ns__getstudent(struct ns__getstudentResponse &ret);
int ns__add(xsd__double a, xsd__double b, xsd__double &result);
int ns__sub(xsd__double a, xsd__double b, xsd__double &result);
int ns__sqrt(xsd__double a, xsd__double &result);
2. 用soapcpp2 生成相关文件:soapcpp2 calc.h
我写了个批处理文件,每次calc.h有修改,我就双击批处理文件,省得每次都要敲命令
3. 编写契约实现代码:calc.cpp
注意: 在calc.cpp里,引用的头文件是soapStub.h,而不再是calc.h,其中有一段是:
1 /******************************************************************************\
2 * *
3 * Server-Side Operations *
4 * *
5 \******************************************************************************/
6
7
8 SOAP_FMAC5 int SOAP_FMAC6 ns__getstudent(struct soap*, struct ns__getstudentResponse &ret);
9
10 SOAP_FMAC5 int SOAP_FMAC6 ns__add(struct soap*, double a, double b, double &result);
11
12 SOAP_FMAC5 int SOAP_FMAC6 ns__sub(struct soap*, double a, double b, double &result);
13
14 SOAP_FMAC5 int SOAP_FMAC6 ns__sqrt(struct soap*, double a, double &result);
2 * *
3 * Server-Side Operations *
4 * *
5 \******************************************************************************/
6
7
8 SOAP_FMAC5 int SOAP_FMAC6 ns__getstudent(struct soap*, struct ns__getstudentResponse &ret);
9
10 SOAP_FMAC5 int SOAP_FMAC6 ns__add(struct soap*, double a, double b, double &result);
11
12 SOAP_FMAC5 int SOAP_FMAC6 ns__sub(struct soap*, double a, double b, double &result);
13
14 SOAP_FMAC5 int SOAP_FMAC6 ns__sqrt(struct soap*, double a, double &result);
这就是我们在calc.cpp要实现的函数,calc.cpp内容如下
#include "soapH.h"
#include "soapStub.h"
// Implementation of the "add" service operation:
int ns__add(struct soap *soap, double a, double b, double &result)
{
result = a + b;
return SOAP_OK;
}
// Implementation of the "sub" service operation:
int ns__sub(struct soap *soap, double a, double b, double &result)
{
result = a - b;
return SOAP_OK;
}
// Implementation of the "sqrt" service operation:
int ns__sqrt(struct soap *soap, double a, double &result)
{
if (a >= 0)
{
result = sqrt(a);
return SOAP_OK;
}
else
return soap_receiver_fault(soap, "Square root of negative number", "I can only take the square root of a non-negative number");
}
int ns__getstudent(struct soap*, struct ns__getstudentResponse &ret)
{
ret.return_.name = "name";
return SOAP_OK;
}
#include "soapStub.h"
// Implementation of the "add" service operation:
int ns__add(struct soap *soap, double a, double b, double &result)
{
result = a + b;
return SOAP_OK;
}
// Implementation of the "sub" service operation:
int ns__sub(struct soap *soap, double a, double b, double &result)
{
result = a - b;
return SOAP_OK;
}
// Implementation of the "sqrt" service operation:
int ns__sqrt(struct soap *soap, double a, double &result)
{
if (a >= 0)
{
result = sqrt(a);
return SOAP_OK;
}
else
return soap_receiver_fault(soap, "Square root of negative number", "I can only take the square root of a non-negative number");
}
int ns__getstudent(struct soap*, struct ns__getstudentResponse &ret)
{
ret.return_.name = "name";
return SOAP_OK;
}
4.这里我用独立程序(控制台程序)来承载服务,当然也可以用cgi方式,不过不是本文讨论的范围。添加main.cpp,实现主函数,内容如下:
#include "ns.nsmap"
int http_get(struct soap *soap)
{
FILE*fd = NULL;
fd = fopen("ns.wsdl", "rb"); //open WSDL file to copy
if (!fd)
{
return 404; //return HTTP not found error
}
soap->http_content = "text/xml"; //HTTP header with text /xml content
soap_response(soap,SOAP_FILE);
for(;;)
{
size_t r = fread(soap->tmpbuf,1, sizeof(soap->tmpbuf), fd);
if (!r)
{
break;
}
if (soap_send_raw(soap, soap->tmpbuf, r))
{
break; //cannot send, but little we can do about that
}
}
fclose(fd);
soap_end_send(soap);
return SOAP_OK;
}
void main(int argc, char **argv)
{
struct soap soap;
int m, s; // master and slave sockets
soap_init(&soap);
soap.fget = http_get;
m = soap_bind(&soap, "192.168.1.19", 8008, 100);
if (m < 0)
soap_print_fault(&soap, stderr);
else
{
fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
for (int i = 1; ; i++)
{
s = soap_accept(&soap);
if (s < 0)
{
soap_print_fault(&soap, stderr);
break;
}
fprintf(stderr, "%d: accepted connection from IP=%d.%d.%d.%d socket=%d", i,
(soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF, s);
if (soap_serve(&soap) != SOAP_OK) // process RPC request
soap_print_fault(&soap, stderr); // print error
fprintf(stderr, "request served\n");
soap_destroy(&soap); // clean up class instances
soap_end(&soap); // clean up everything and close socket
}
}
soap_done(&soap); // close master socket and detach context
}
int http_get(struct soap *soap)
{
FILE*fd = NULL;
fd = fopen("ns.wsdl", "rb"); //open WSDL file to copy
if (!fd)
{
return 404; //return HTTP not found error
}
soap->http_content = "text/xml"; //HTTP header with text /xml content
soap_response(soap,SOAP_FILE);
for(;;)
{
size_t r = fread(soap->tmpbuf,1, sizeof(soap->tmpbuf), fd);
if (!r)
{
break;
}
if (soap_send_raw(soap, soap->tmpbuf, r))
{
break; //cannot send, but little we can do about that
}
}
fclose(fd);
soap_end_send(soap);
return SOAP_OK;
}
void main(int argc, char **argv)
{
struct soap soap;
int m, s; // master and slave sockets
soap_init(&soap);
soap.fget = http_get;
m = soap_bind(&soap, "192.168.1.19", 8008, 100);
if (m < 0)
soap_print_fault(&soap, stderr);
else
{
fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
for (int i = 1; ; i++)
{
s = soap_accept(&soap);
if (s < 0)
{
soap_print_fault(&soap, stderr);
break;
}
fprintf(stderr, "%d: accepted connection from IP=%d.%d.%d.%d socket=%d", i,
(soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF, s);
if (soap_serve(&soap) != SOAP_OK) // process RPC request
soap_print_fault(&soap, stderr); // print error
fprintf(stderr, "request served\n");
soap_destroy(&soap); // clean up class instances
soap_end(&soap); // clean up everything and close socket
}
}
soap_done(&soap); // close master socket and detach context
}
5.修改ns.wsdl
将location属性修改和main函数里面的bind匹配,否则会出现连接错误
<service name="Service">
<documentation>gSOAP 2.8.5 generated service definition</documentation>
<port name="Service" binding="tns:Service">
<SOAP:address location="http://192.168.1.19:8008"/>
</port>
</service>
<documentation>gSOAP 2.8.5 generated service definition</documentation>
<port name="Service" binding="tns:Service">
<SOAP:address location="http://192.168.1.19:8008"/>
</port>
</service>
6.包含文件,整个工程的文件结构如图:
6.编译,ok
浙公网安备 33010602011771号