基于gSOAP使用头文件的C语言版web service开发过程例子
基于gSOAP使用头文件的C语言版web service开发过程例子
一服务端
1 打开VS2005,创建一个工程,命名为calcServer。
2 添加一个头文件calc.h,编辑内容如下:
1//gsoap ns service name: calc 2//gsoap ns service port: http://localhost/calc.wsdl 3//gsoap ns service location: http://localhost 4//gsoap ns service executable: calc.cgi 5//gsoap ns service encoding: encoded 6//gsoap ns service type: calcPortType 7//gsoap ns schema namespace: urn:add //gsoap ns service method-documentation: add Sums two values int ns__add(double a, double b, double *result); //gsoap ns service method-documentation: sub Subtracts two values int ns__sub(double a, double b, double *result); //gsoap ns service method-documentation: mul Multiplies two values int ns__mul(double a, double b, double *result); //gsoap ns service method-documentation: div Divides two values int ns__div(double a, double b, double *result); //gsoap ns service method-documentation: pow Raises a to b int ns__pow(double a, double b, double *result); |
说明:
1) 前面的1-7行在生成的XML文件里会有所体现。
2)第一行定义了服务名,如果第一行写成“//gsoap ns service name: calc1”,编译时则将“calc1”当作服务名称,生成的文件中也会使用这个名称。
D:\gSOAP_study\gSOAP_test_calc\calc_server>soapcpp2.exe -c -e calc.h ** The gSOAP code generator for C and C++, soapcpp2 release 2.8.15 ** Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc. ** All Rights Reserved. This product is provided "as is", without any warranty. ** The soapcpp2 tool is released under one of the following two licenses: ** GPL or the commercial license by Genivia Inc. Saving soapStub.h annotated copy of the source input Saving soapH.h interface declarations Using ns service name: calc1 Using ns service encoding: encoded Using ns service location: http://localhost/calc.wsdl http://localhost Using ns service executable: calc.cgi Using ns schema namespace: urn:add Saving calc1.wsdl Web Service description Saving calc1.add.req.xml sample SOAP/XML request Saving calc1.add.res.xml sample SOAP/XML response Saving calc1.sub.req.xml sample SOAP/XML request Saving calc1.sub.res.xml sample SOAP/XML response Saving calc1.mul.req.xml sample SOAP/XML request Saving calc1.mul.res.xml sample SOAP/XML response Saving calc1.div.req.xml sample SOAP/XML request Saving calc1.div.res.xml sample SOAP/XML response Saving calc1.pow.req.xml sample SOAP/XML request Saving calc1.pow.res.xml sample SOAP/XML response Saving calc1.nsmap namespace mapping table Saving ns.xsd XML schema Saving soapClient.c client calling stubs Saving soapClientLib.c client stubs with serializers (use only for libs) Saving soapServer.c server request dispatcher Saving soapServerLib.c server request dispatcher with serializers (use only for libs) Saving soapC.c serializers Compilation successful |
3) 第2行定义了calc.wsdl的路径
4) 第3行定义了服务地址,在客服端通过这个地址再加上端口即个访问此服务端。
5)第4行也是定义了一种地址,在calc.wsdl文件里体现如下:
<service name="calc"> <documentation>gSOAP 2.8.15 generated service definition</documentation> <port name="calc" binding="tns:calc"> <SOAP:address location="http://localhost/calc.wsdl http://localhost/calc.cgi"/> </port> <port name="calc" binding="tns:calc"> <SOAP:address location="http://localhost/calc.wsdl"/> <SOAP:address location="http://localhost"/> </port> </service> |
6) 第5 行定义了输出输出量的编码方式,使用了此行在使用soapcpp2.exe编译头时需要加“-e ”参数
<binding name="calc" type="tns:calcPortType"> <SOAP:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="add"> <SOAP:operation style="rpc" soapAction=""/> <input> <SOAP:body use="encoded" namespace="http://tempuri.org/ns.xsd" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <SOAP:body use="encoded" namespace="http://tempuri.org/ns.xsd" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="sub"> <SOAP:operation style="rpc" soapAction=""/> <input> <SOAP:body use="encoded" namespace="http://tempuri.org/ns.xsd" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <SOAP:body use="encoded" namespace="http://tempuri.org/ns.xsd" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="mul"> <SOAP:operation style="rpc" soapAction=""/> <input> <SOAP:body use="encoded" namespace="http://tempuri.org/ns.xsd" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <SOAP:body use="encoded" namespace="http://tempuri.org/ns.xsd" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="div"> <SOAP:operation style="rpc" soapAction=""/> <input> <SOAP:body use="encoded" namespace="http://tempuri.org/ns.xsd" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <SOAP:body use="encoded" namespace="http://tempuri.org/ns.xsd" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="pow"> <SOAP:operation style="rpc" soapAction=""/> <input> <SOAP:body use="encoded" namespace="http://tempuri.org/ns.xsd" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <SOAP:body use="encoded" namespace="http://tempuri.org/ns.xsd" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding> |
7) 第6行定义了wsdl中的 <portType >
<portType name="calcPortType"> <operation name="add"> <documentation>Sums two values</documentation> <input message="tns:addRequest"/> <output message="tns:addResponse"/> </operation> <operation name="sub"> <documentation>Subtracts two values</documentation> <input message="tns:subRequest"/> <output message="tns:subResponse"/> </operation> <operation name="mul"> <documentation>Multiplies two values</documentation> <input message="tns:mulRequest"/> <output message="tns:mulResponse"/> </operation> <operation name="div"> <documentation>Divides two values</documentation> <input message="tns:divRequest"/> <output message="tns:divResponse"/> </operation> <operation name="pow"> <documentation>Raises a to b</documentation> <input message="tns:powRequest"/> <output message="tns:powResponse"/> </operation> </portType> |
8) 每个函数前的注释对应calc.wsdl文件里<documentation>如上图中的每个操作的<documentation>:
<documentation>Sums two values</documentation>
3 将gSOAP包里的bin/win32下的soapcpp2.exe和gSOAP包里的stdsoap2.h、stdsoap2.c或stdsoap2.cpp拷贝到前面创建的工程文件夹里。
4 启动dos窗口并切换到此目录下使用soapcpp2.exe生成相应的文件。
相关参数可使用“soapcpp2.exe –help”查询,
这里我使用了soapcpp2.exe –c –e calc.h命令,只表示生成C代码,此时会生成服务端和客户端的文件及一些头文件。 包括soapC.c 、soapClient.c、soapClientLib.c、soapServer.c、soapServerLib.c、soapH.h、soapStub.h等文件。
如果是c++,则“.c”文件换成“.cpp”。
如果只想生成服务端文件需要加参数“- S”,如果只生成客户端程序加参数“-C”。
5 将服务端需要的文件soapC.c 、soapServer.c、soapH.h、soapStub.h、stdsoap2.h、stdsoap2.c文件添加到工程里。
不需要添加soapServerLib.c文件。
此处一定要用stdsoap2.c,如果用stdsoap2.cpp会出错。
原则是要么全部是.c的文件格式,要么全部是.cpp的文件格式。
6 创建main函数文件:
#include "soapH.h" #include "calc.nsmap" #include "stdsoap2.h" #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { SOAP_SOCKET m, s; /* master and slave sockets */ struct soap soap; soap_init(&soap); if (argc < 2) soap_serve(&soap); /* serve as CGI application */ else { m = soap_bind(&soap, NULL, atoi(argv[1]), 100); if (!soap_valid_socket(m)) { soap_print_fault(&soap, stderr); exit(-1); } fprintf(stderr, "Socket connection successful: master socket = %d\n", m); for ( ; ; ) { s = soap_accept(&soap); fprintf(stderr, "Socket connection successful: slave socket = %d\n", s); if (!soap_valid_socket(s)) { soap_print_fault(&soap, stderr); exit(-1); } soap_serve(&soap); soap_end(&soap); } } return 0; } int ns__add(struct soap *soap, double a, double b, double *result) { *result = a + b; return SOAP_OK; } int ns__sub(struct soap *soap, double a, double b, double *result) { *result = a - b; return SOAP_OK; } int ns__mul(struct soap *soap, double a, double b, double *result) { *result = a * b; return SOAP_OK; } int ns__div(struct soap *soap, double a, double b, double *result) { if (b) *result = a / b; else { char *s = (char*)soap_malloc(soap, 1024); sprintf(s, "<error xmlns=\"http://tempuri.org/\">Can't divide %f by %f</error>", a, b); return soap_sender_fault(soap, "Division by zero", s); } return SOAP_OK; } int ns__pow(struct soap *soap, double a, double b, double *result) { *result = pow(a, b); if (soap_errno == EDOM) /* soap_errno is like errno, but compatible with Win32 */ { char *s = (char*)soap_malloc(soap, 1024); sprintf(s, "Can't take the power of %f to %f", a, b); sprintf(s, "<error xmlns=\"http://tempuri.org/\">Can't take power of %f to %f</error>", a, b); return soap_sender_fault(soap, "Power function domain error", s); } return SOAP_OK; } |
7 在工程“propertis”-> “configuration Proterties”->“Debugging”->“command arguments”里添加端口参数4546。
8 build
9 启动调试
10 在浏览器里输入“http://localhost:4546”。 如果得到如下信息则说明服务已经正常启动:
This XML file does not appear to have any style information associated with it. The document tree is shown below. <SOAP-ENV:Fault xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns="http://tempuri.org/ns.xsd"> <faultcode>SOAP-ENV:Client</faultcode> <faultstring>HTTP GET method not implemented</faultstring> </SOAP-ENV:Fault> |
二客户端
1 如上炮制。
只需将上面的soapServer.c换成soapClient.c
2 编写客户端main函数文件
#include "soapH.h" #include "calc.nsmap" #include <stdio.h> #include <stdlib.h> #include "stdsoap2.h" const char server[] = "http://localhost:4546";//"http://websrv.cs.fsu.edu/~engelen/calcserver.cgi"; /* = "http://localhost:8080"; to test against samples/webserver */ int main(int argc, char **argv) { struct soap soap; double a, b, result; if (argc < 4) { fprintf(stderr, "Usage: [add|sub|mul|div|pow] num num\n"); exit(0); } soap_init1(&soap, SOAP_XML_INDENT); //soap_init(&soap); //printf("add(%f,%f) \n",argv[2],argv[3]); a = strtod(argv[2], NULL); b = strtod(argv[3], NULL); switch (*argv[1]) { case 'a': printf("add(%f,%f) \n",a,b); soap_call_ns__add(&soap, server, NULL, a, b, &result); break; case 's': soap_call_ns__sub(&soap, server, "", a, b, &result); break; case 'm': soap_call_ns__mul(&soap, server, "", a, b, &result); break; case 'd': soap_call_ns__div(&soap, server, "", a, b, &result); break; case 'p': soap_call_ns__pow(&soap, server, "", a, b, &result); break; default: fprintf(stderr, "Unknown command\n"); exit(0); } if (soap.error) { printf("abcd\n"); soap_print_fault(&soap, stderr); exit(1); } else printf("result = %f\n", result); soap_destroy(&soap); soap_end(&soap); soap_done(&soap); return 0; } |
此文件中已经设置了服务端的地址和端口。
3在工程“propertis”-> “configuration Proterties”->“Debugging”->“command arguments”里添加参数“add 4.2 3.6”。表示进行两个数的加法
4 build
5 debug。运行,此时会得到两个参数的计算结果。
三注意事项
1 int可以向double转,但double不能向int转,如4.2会变成0.
基于gSOAP使用头文件的C语言版web service开发过程例子的更多相关文章
- 关于:基于http协议大文件断点续传上传至web服务器
关键部分 前端用file.slice()分块 前端用FileReader获取每一分块的md5值 后端用MultipartFile接受分块文件 后端用FileOutputStream拼装分块文件 话不多 ...
- 浅谈c语言的线性表的基本操作———基于严蔚敏的数据结构(c语言版)
主要讲的是线性表的创建,插入及删除: 0. 线性表的建立,对于这类操作主要是利用了结构体的性质,对于定义的线性表的特性主要有三点:首先 Typedef struct { ElemType *ele ...
- 为什么C语言会有头文件
前段时间一个刚转到C语言的同事问我,为什么C会多一个头文件,而不是像Java和Python那样所有的代码都在源文件中.我当时回答的是C是静态语言很多东西都是需要事先定义的,所以按照惯例我们是将所有的定 ...
- C预编译, 预处理, C/C++头文件, 编译控制,
在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...
- C++笔记:头文件的作用和写法
from://http://ceeji.net/blog/c%E7%AC%94%E8%AE%B0%EF%BC%9A%E5%A4%B4%E6%96%87%E4%BB%B6%E7%9A%84%E4%BD% ...
- CGAL 获取相关功能的依赖头文件
CGAL 获取相关功能的依赖头文件 由于CGAL是header include only.只需要头文件就可以实现相关的功能.有时候为了实现一个简单的功能, 在研究具体实现的时候能够知道这个功能对应的头 ...
- Objective-C声明在头文件和实现文件中的区别
Objective-C声明在头文件和实现文件中的区别 转自codecloud(有整理) 调试程序的时候,突然想到这个问题,百度一下发现有不少这方面的问答,粗略总结一下: 属性写在.h文件中和在.m文件 ...
- linux 内核头文件 linux kernel header
概述:在进行有关系统软件的安装的时候(编译一个新的驱动,或者安装一个系统级别的测试工具,例如systemtap),经常需要重新编译内核,相应的问题往往与内核头文件有关.那么,什么是内核头文件,为什么需 ...
- [C++] C语言及C++语言中包含的头文件名称,及作用
头文件主目录include 头文件目录中总共有32个.h头文件.其中主目录下有13个,asm子目录中有4个,linux子目录中有10个,sys子目录中有5个.这些头文件各自的功能如下,具体的作用和所包 ...
随机推荐
- django模型中的抽象类(abstract)
首先介绍下django的模型有哪些属性:先看例子: Django 模型类的Meta是一个内部类,它用于定义一些Django模型类的行为特性.以下对此作一总结: abstract 这个属性是定义当前的模 ...
- 注意map<> 的[]
其实在之前一篇关于map的基本操作中已经提到过注意[]操作,这里再强调一下. 先看下面的程序: #include<iostream> #include<map> using n ...
- 《OD学hadoop》第二周0702
大数据离线计算hadoop2.x 三周(6天) markdown文本剪辑器 罗振宇--跨年演讲,时间的朋友 http://tech.163.com/16/0101/11/BC87H8DF000915B ...
- 观察者模式最佳案例实现[JAVA][原创]
/** * American Stock Exchange market(ASE) has a list of stocks.A stock object has two perspective in ...
- 另类方法解决设计Web页面出现:Error Creating Control
在B/S开发的过程中,经常会遇到这样的提示:Error Creating Control ,而这些页面明明之前是可以打开的,但还是出现如下图所示: 网上找到的方法是把控件初始化放在OnInit里去写, ...
- openerp 7 在ubuntu上设置开机启动
我们要让openerp开机运行起来. 第一步,先进入系统目录: cd /etc/init.d 第二步,创建文件.命名为openerp-server sudo vi openepr-server 第三步 ...
- MapView的用法
一.MapView 1.显示用户的位置点(用蓝色圆点标记) mapView.showsUserLocation = YES; 2.代理方法 1> 当定位到用户的位置就会调用 - (void)ma ...
- 一个基于PDO的数据库操作类(新) 一个PDO事务实例
<?php /* * 作者:胡睿 * 日期:2011/03/19 * 电邮:hooray0905@foxmail.com * * 20110319 * 常用数据库操作,如:增删改查,获取单条记录 ...
- exception is org.hibernate.exception.DataException: Could not execute JDBC batch update at
没有什么问题,但是却报了Could not execute JDBC batch update的错,主要是配置文件设置了关联,数据却没有关联造成的,只要数据正确就没有问题. 另外,造成这个原因的还可能 ...
- ubuntu下安装Matlab
(注:本文部分内容转自互联网) 一. 安装程序Step 1:下载matlab的安装文件至主目录下,讲matlab文件重命名为Mathworks.Matlab.R2012a.Unix.isoStep 2 ...