天天看点

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++方式

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++方式

服务端我们需要的是这些

Gsoap服务器 c++方式

客户端我们需要的是(修改内容)

Win + R 打开 cmd 输入 soapcpp2 -CLx 头文件

生成如下文件

Gsoap服务器 c++方式

我们一开始创建的头文件在这里就没有用处了. 但是会用在以后加别的功能,就需要在原来的头文件里加上接口,并再用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++方式

接口具体实现:

Gsoap服务器 c++方式

因为我是用的服务代理方式继承的soap结构体,所以需要给CalculatorService这个类具体实现函数.

客户端:

客户端的操作也跟服务端类似,MFC程序上#include “Calculator.nsmap”这个命名空间需要放到cpp文件里

Gsoap服务器 c++方式

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++方式

1.6 客户端调用

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

CalculatorProxy demo;          //CalculatorProxy 这个类是根据       
                               //soapCalculatorProxy.h 这个来的自己看看
double num1=,num2=,m_Result=; (自己脑补初始化)
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

继续阅读