gsoap 远程调用举例

心已赠人 2023-02-12 09:29 198阅读 0赞

gsoap 远程调用举例

gsoap生成Web Service框架代码。这里通过gsoap官网**Example XML SOAP server ©Example XML SOAP client ©**例子来实现sgoap生成框架,并实现远程调用。

gsoap官网例程:https://www.genivia.com/dev.html\#server-c

img

1、SOAP服务器

将gsoap安装路径下的importcustom文件夹,stdsoap2.hstdsoap2.h拷贝到需要生成文件的路径中。

利用wsdl2h工具和wsdl文档来生成.h服务接口。然后通过soapcpp2工具和.h文件生成底层代码和接口。

  1. $ wsdl2h -c -o calc.h http://www.genivia.com/calc.wsdl
  2. $ soapcpp2 -S -L -x calc.h

最终生成服务器代码。这里需要用到的文件主要有soapC.c soapServer.c stdsoap2.c calcserver.c stdsoap2.h soapStub.h soapH.hcalcserver.c是我手动创建的,用来实现wsdl文档中的接口和主函数。
在这里插入图片描述
calcserver.c文件主要内容如下,代码来自gsoap官网案例。代码稍微有点问题,明明是C的例子,里面却出现了C++代码,这里直接将C++代码全部注释掉,不适用pow功能。

  1. #include "calc.nsmap" // XML namespace mapping table (only needed once at the global level)
  2. #include "soapH.h" // server stubs, serializers, etc.
  3. int main()
  4. {
  5. struct soap *soap = soap_new1(SOAP_XML_INDENT);
  6. soap_set_namespaces(&soap, namespaces);
  7. if (!soap_valid_socket(soap_bind(soap, NULL, 8080, 10))) // port 8080 and small BACKLOG queue for iterative servers
  8. exit(EXIT_FAILURE);
  9. /* 阻塞在soap_accept处,当有远程调用产生时,接收远程调用并进行相应的处理。 */
  10. while (soap_valid_socket(soap_accept(soap)))
  11. {
  12. printf("accept ok\r\n");
  13. if (soap_serve(soap) != SOAP_OK)
  14. break;
  15. soap_destroy(soap); // delete deserialized C++ instances
  16. soap_end(soap); // delete other managed data
  17. }
  18. soap_print_fault(soap, stderr);
  19. soap_free(soap); // free the soap struct context data
  20. }
  21. /* 以下是关于wsdl接口的实现。当客户端对服务器进行远程调用时,将会调用以下对应的函数。 */
  22. int ns2__add(struct soap *soap, double a, double b, double *result)
  23. {
  24. printf("ns2__add called\r\n");
  25. /* 这里把加法改成乘法,证明我们的调用没有问题。 */
  26. *result = a * b;
  27. return SOAP_OK;
  28. }
  29. int ns2__sub(struct soap *soap, double a, double b, double *result)
  30. {
  31. *result = a - b;
  32. return SOAP_OK;
  33. }
  34. int ns2__mul(struct soap *soap, double a, double b, double *result)
  35. {
  36. *result = a * b;
  37. return SOAP_OK;
  38. }
  39. int ns2__div(struct soap *soap, double a, double b, double *result)
  40. {
  41. if (b == 0.0)
  42. {
  43. char *msg = (char*)soap_malloc(soap, 1024);
  44. snprintf(msg, 1024, "Trying to divide %f by zero", a);
  45. return soap_sender_fault(soap, msg, NULL);
  46. }
  47. *result = a / b;
  48. return SOAP_OK;
  49. }
  50. int ns2__pow(struct soap *soap, double a, double b, double *result)
  51. {
  52. // *result = ::pow(a, b);
  53. // // soap_errno is like errno, but compatible with Win32
  54. // if (soap_errno == EDOM)
  55. // {
  56. // char *msg = (char*)soap_malloc(soap, 1024);
  57. // snprintf(msg, 1024, "<error xmlns=\"http://tempuri.org/\">Can't take power of %f to %f</error>", a, b);
  58. // return soap_sender_fault(soap, "Power function domain error", s);
  59. // }
  60. return SOAP_OK;
  61. }

完成calcserver.c后,编译server并运行。我这里是通过wsl编译运行的。

  1. $ gcc soapC.c soapServer.c stdsoap2.c calcserver.c -o calcserver
  2. $ ./calcserver

这时服务器的ip使我们的本机IP:192.168.x.x,然后端口号是上面设置的8080。服务器已经搭建完成了,接下来进行client端开发,来访问我们的服务器。


2、SOAP客户端

Client操作流程和Server类似。同样的操作步骤,修改命令参数即可。这里将Client代码路径修改一下,不要和Server放在同一路径下,因为生成的soapStub.h有略微差异,后面不方便同时修改客户端服务端代码。

根据gsoap官网的教程,生成代码。操作如下:

  1. $ wsdl2h -c -o calc.h http://www.genivia.com/calc.wsdl
  2. $ soapcpp2 -CL -x calc.h

最终生成客户端代码。这里需要用到的文件主要有soapC.c soapClient.c stdsoap2.c calcclient.c stdsoap2.h soapStub.h soapH.hcalcClient.c是我手动创建的,用来实现main函数对Server进行访问调用。
在这里插入图片描述
calcserver.c文件主要内容如下,代码来自gsoap官网案例。这里对ns2__add进行远程调用,发送调用信息给服务器,服务器收到调用信息再调用具体实现函数。因为之前已经修改过add了,所以这里调用以后应该是乘法结构。

  1. #include "calc.nsmap" // XML namespace mapping table (only needed once at the global level)
  2. #include "soapH.h" // client stubs, serializers, etc.
  3. int main()
  4. {
  5. struct soap *soap = soap_new(); // allocate and initialize a context
  6. double sum;
  7. soap->connect_timeout = 10; // connect within 10s
  8. soap->send_timeout = 5; // send timeout is 5s
  9. soap->recv_timeout = 5; // receive timeout is 5s
  10. soap->socket_flags = MSG_NOSIGNAL;
  11. if (soap_call_ns2__add(soap, NULL, NULL, 1.23, 4.56, &sum) == SOAP_OK)
  12. printf("Sum = %g\n", sum);
  13. else
  14. soap_print_fault(soap, stderr);
  15. soap_destroy(soap); // delete managed deserialized C++ instances
  16. soap_end(soap); // delete other managed data
  17. soap_free(soap); // free the soap struct context data
  18. }

它这里的给的例子不是调用我们自己服务器的,所以需要将它调用的链接修改我们自己服务器的地址和端口号。在soapClient.c中,对相应的代码进行修改,soap_endpoint是用来控制访问地址的,这里修改成我们服务器的。

  1. SOAP_FMAC5 int SOAP_FMAC6 soap_send_ns2__add(struct soap *soap, const char *soap_endpoint, const char *soap_action, double a, double b)
  2. { struct ns2__add soap_tmp_ns2__add;
  3. if (soap_endpoint == NULL)
  4. // soap_endpoint = "http://websrv.cs.fsu.edu/~engelen/calcserver.cgi";
  5. soap_endpoint = "192.168.x.x:8080";

完成calcclient.c后,编译client并运行。我这里是通过wsl编译运行的。

  1. $ gcc soapC.c calcclient.c soapClient.c stdsoap2.c -o calcclient
  2. $ ./calcclient

输出结果如下:

在这里插入图片描述


3、总结

以上就是利用gsoap工具通过wsdl文档来生成web service框架,我们只需要完成wsdl文档的接口就行了。


发表评论

表情:
评论列表 (有 0 条评论,198人围观)

还没有评论,来说两句吧...

相关阅读