Gsoap服务器 c++方式

敬畏:
网上的向导文档:https://www.genivia.com/doc/soapdoc2.html#tth_sEc7.2.7
官方工具:http://download.csdn.net/download/rhddlr/9960889
概述:
服务端我采用的单线程的控制台程序 创建了一个空项目,再创建一个cpp文件,等下用来实现头文件中声明的接口.
客户端我采用的是MFC对话框程序,把文件放入工程后编译几次,需要把stdafx.h加到已经编译出来的文件里面

1.Gsoap服务器的搭建流程
1.1 先创建一个头文件,这个头文件里面放的就是你要在Gsoap服务端实现的功能
可以看官方向导里面的 7.2.3 和 7.2.4 注意的主要是头文件的注释部分和函数声明需要返回值这两点.
注释部分:

// Content of file "calc.h": 
//gsoap ns service name: Calculator 
//gsoap ns service protocol: SOAP 
//gsoap ns service style: rpc 
//gsoap ns service encoding: encoded 
//gsoap ns service location: http://127.0.0.1:8087 
//gsoap ns schema namespace: urn:calc 
//gsoap ns service method-action: add "" 

Calculator: 会成为你按c++方式编译文件后的名字,我编译之后生成了这种soapCalculatorserver.h soapCalculatorserver.cpp
location: 如果在客户端调用接口方法时,没有输入服务端地址,方法执行时将自动调用此处的地址做为服务器地址
rpc : webserver类型表示远程调用
protocol : webserver 所使用的协议
encoding: 编码格式Literal、Encoded
calc : 命名空间
Gsoap服务器 c++方式_第1张图片
method-action: 函数说明

1.2 函数接口和参数部分:

int ns__sub(double a, double b, double &result); 

1.这里函数的返回值表示的是 GSOAP内部的返回值.
真正的返回值应该用&result 这种参数指针的方式返回. 如果没有参数指针的话用soapcpp2.exe编译时会出错.
2.多个参数传出,在接口中必须使用结构体,在结构体里面放你想要的参数,函数参数写成结构体的指针

struct ns__personResponse{
int age;
char * name;
char * address;
};
int ns__person( char * buf_in, struct ns__personResponse *buf_out );

3.如果要传结构体,那么必须在结构体中再套一层结构体

struct ns__person{
int age;
char * name;
char * address; 
};
struct ns__personResponse{
int ret;
struct ns__person person;
};
int ns__person( char* buf_in, struct ns__personResponse * buf_out );

1.3 编译方式
我采用的是服务代理方式: soapcpp2.exe -i calc.h
然后需要把这里面的文件放到服务端和客户端工程里面
生成的服务代理类和对象从struct soap继承而来得到文件
Gsoap服务器 c++方式_第2张图片

服务端我们需要的是这些
Gsoap服务器 c++方式_第3张图片

客户端我们需要的是(修改内容)
Win + R 打开 cmd 输入 soapcpp2 -CLx 头文件
生成如下文件
Gsoap服务器 c++方式_第4张图片
我们一开始创建的头文件在这里就没有用处了. 但是会用在以后加别的功能,就需要在原来的头文件里加上接口,并再用soapcpp2.exe编译.
MFC工程中添加文件出问题:
1.
error LNK2001: 无法解析的外部符号 _namespaces”解决方法:添加编译宏WITH_NONAMESPACES
2.
error LNK2005: _namespaces 已经在 .obj 中定义:工程包含了多个nsmap文件或者nsmap文件被包含在头文件中,可删除多余的nsmap文件,并将包含nsmap文件代码移至cpp中

1.4 编译程序
服务端:
在空项目里面添加完上述文件之后,再创建一个cpp文件在具体实现我们定义的接口
头文件include如图:
这里写图片描述
接口具体实现:
Gsoap服务器 c++方式_第5张图片
因为我是用的服务代理方式继承的soap结构体,所以需要给CalculatorService这个类具体实现函数.

客户端:
客户端的操作也跟服务端类似,MFC程序上#include “Calculator.nsmap”这个命名空间需要放到cpp文件里
Gsoap服务器 c++方式_第6张图片

include “stdafx.h” 可以在编译过程中看出需要在哪里加上.

1.5 服务端运行
服务端运行分三个部分:
1.代理服务对象创建:
2.使用对象的bind(NULL,8087,100)
函数绑定端口和设定队列长度,参数说明: 服务器地址,端口,等待连接队列的最大长度
3.接收函数 accept(),运行这个函数 服务端就会进入接收请求状态,可以设置一个变量获取这个函数的返回值socketid(int 类型).
4.接收到之后 如果socketid不为0 , 再调用serve() 函数这个函数会解析客户端的请求,函数返回值是int型 除了0其他都是错误,对象调用soap_stream_fault(std::cerr)可以把错误消息返回到客户端上去(这只在客户端是控制台时我用到过,改成MFC客户端后就没用到了,因为我太菜)
5.重新初始化函数和销毁函数我也没太用到,象征性的写一下,多线程可能会用到
Gsoap服务器 c++方式_第7张图片

1.6 客户端调用
客户端跟服务端一样,创建一个类对象

CalculatorProxy demo;          //CalculatorProxy 这个类是根据       
                               //soapCalculatorProxy.h 这个来的自己看看
double num1=6,num2=1,m_Result=0; (自己脑补初始化)
demo.sub(num1,num2,m_Result); // 6-2 = 4 

m_Result 就是4 ,结果了
如果有更好的方法请大佬指教~~~

1.7
参考文档:
http://blog.csdn.net/flyfish1986/article/details/7593224 这个参考文档不错
http://blog.csdn.net/comman1999/article/details/1967907 encoding:说明
http://blog.csdn.net/byxdaz/article/details/51679117
http://blog.csdn.net/wang_zheng_kai/article/details/20699901
http://www.cppblog.com/qiujian5628/archive/2008/06/19/54019.html 例子
http://blog.csdn.net/flyfish1986/article/details/7593224 源码流程
https://www.genivia.com/docs.html 英文文档
错误码表:
https://wenku.baidu.com/view/f9000f68af1ffc4ffe47ac3e.html

你可能感兴趣的:(gsoap-c++)