基于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开发过程例子的更多相关文章

  1. 关于:基于http协议大文件断点续传上传至web服务器

    关键部分 前端用file.slice()分块 前端用FileReader获取每一分块的md5值 后端用MultipartFile接受分块文件 后端用FileOutputStream拼装分块文件 话不多 ...

  2. 浅谈c语言的线性表的基本操作———基于严蔚敏的数据结构(c语言版)

    主要讲的是线性表的创建,插入及删除: 0. 线性表的建立,对于这类操作主要是利用了结构体的性质,对于定义的线性表的特性主要有三点:首先 Typedef struct { ElemType   *ele ...

  3. 为什么C语言会有头文件

    前段时间一个刚转到C语言的同事问我,为什么C会多一个头文件,而不是像Java和Python那样所有的代码都在源文件中.我当时回答的是C是静态语言很多东西都是需要事先定义的,所以按照惯例我们是将所有的定 ...

  4. C预编译, 预处理, C/C++头文件, 编译控制,

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

  5. 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% ...

  6. CGAL 获取相关功能的依赖头文件

    CGAL 获取相关功能的依赖头文件 由于CGAL是header include only.只需要头文件就可以实现相关的功能.有时候为了实现一个简单的功能, 在研究具体实现的时候能够知道这个功能对应的头 ...

  7. Objective-C声明在头文件和实现文件中的区别

    Objective-C声明在头文件和实现文件中的区别 转自codecloud(有整理) 调试程序的时候,突然想到这个问题,百度一下发现有不少这方面的问答,粗略总结一下: 属性写在.h文件中和在.m文件 ...

  8. linux 内核头文件 linux kernel header

    概述:在进行有关系统软件的安装的时候(编译一个新的驱动,或者安装一个系统级别的测试工具,例如systemtap),经常需要重新编译内核,相应的问题往往与内核头文件有关.那么,什么是内核头文件,为什么需 ...

  9. [C++] C语言及C++语言中包含的头文件名称,及作用

    头文件主目录include 头文件目录中总共有32个.h头文件.其中主目录下有13个,asm子目录中有4个,linux子目录中有10个,sys子目录中有5个.这些头文件各自的功能如下,具体的作用和所包 ...

随机推荐

  1. 如何通过session控制单点登录

    web服务器为每一个浏览器实例对应一个session.这个session有自己的一个独立id,这个id保存在浏览器的cookie中(这个cookie貌似随着这个浏览器实例的关闭而清除),访问web服务 ...

  2. iPhone 已停用

    如果你的iPhone上出现了如下的显示,你可以参考苹果官网上的  iOS设备已停用 如果你看到了这篇文章,你比我幸运多了. 参考这一个条目,你也许就不会丢失里面的数据了. 可怜的我,出现这个问题时还没 ...

  3. linux 系统 tar 的用法详解

    [root@localhost xu]# tar --help 用法: tar [选项...] [FILE]... GNU ‘tar’ 将许多文件一起保存至一个单独的磁带或磁盘归档,并能从归档中单独还 ...

  4. orm 通用方法——GetOneModel 条件查询一个对象

    数据连接层的方法封装成通用方法是很有必要,节省不必要的重复写代码. Golang的orm.xorm框架没有封装这些操作. 这里是一个查询单个对象的方法. 此处抛砖引玉,大家继续完善. 通用方法定义代码 ...

  5. spring mvc出现 Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'endtime'

    在使用spring mvc中,绑定页面传递时间字符串数据给Date类型是出错: Failed to convert property value of type [java.lang.String] ...

  6. js中encode、decode的应用说明

    escape 方法 返回一个可在所有计算机上读取的编码 String 对象. function escape(charString : String) : String 参数 charString 必 ...

  7. 漫游Kafka实现篇之分布式

    Zookeeper节点标记 当路径中的元素包括在方括号里比如[xyz],则表示xyz表示的值是不固定的,每个可能的值都有一个Zookeeper节点.比如/topics/[topic]表示每个topic ...

  8. Windows系统下Memcached缓存系列一:Couchbase(服务器端)和CouchbaseClient(c#客户端)的安装教程

    一:服务器端的安装  官网 http://www.couchbase.com/download  我的电脑是64位的win7,找到对应下载windows版本的服务器端缓存,大概90M的样子 运行期间可 ...

  9. java注解Annotation

    扯扯注解的蛋 为什么学习注解?学习注解有什么好处?学完能做什么? 1.能够读懂别人的代码,特别是框架相关的代码 2.让编程更加简洁,代码更加清晰 3.让别人高看你一眼 注解是java1.5引入的 概念 ...

  10. 纵观minecraft 游戏作者的世界观

    minecraft 这款游戏 独特的游戏背景 与 模式 深受我爱 ,游戏的音乐制作方面也是独具一格 但是 整个游戏的风气 充满孤独的色彩 抑郁惆怅的音乐 每当在日出时 响起 ,当你进入生存模式之后 开 ...