前言:因工作需要用到webService,在网上百度了一下实现方案,主要分两种——QtSoap和gsoap,考虑到QtSoap也是第三方服务(Qt本身不提供这个模块),于是选择使用QT + gsoap实现对webService的访问。然而,实际操作的时候遇到了不少问题,使用网上的demo并不能顺利地编译和运行,并且编译报错内容看的自己有点懵逼,恰巧看到有两篇介绍VS+gsoap的方案,感觉比较靠谱,就先用VS2015编译了一下,发现可以运行,所以本文将使用VS和Qt的方法都记录了下来。
备注(电脑系统和软件版本):win10系统,VS2015,QT5.9.4。
一、下载gsoap压缩包并解压:
1. 2.8.67版本下载地址:
2. 下载的压缩包无需安装,下载完成后解压到任意位置(当然,路径最好不要包含中文,我是直接解压到D盘的),然后添加环境变量,因为gsoap需要用到cmd和shell命令。
3. 备注:
(1)不清楚什么原因,该链接下载速度很慢,我第一次下载后解压提示压缩包损坏,第二次下载的才能正常使用;
(2)添加环境变量后,Shift加鼠标右键可以直接打开Powershell窗口,之前是cmd控制台窗口。添加环境变量截图如下:
二、通过VS2015 + gsoap创建webService服务端和客户端:
1. 开发自己的服务端和客户端可以参考两篇博客,这里附上链接,基本上按照博客指导可以完成服务端创建和客户端的运行。
服务端:
客户端:https://blog.csdn.net/testcs_dn/article/details/51526051
2. 这里记录一下实际操作的几个步骤,里面主要是一些不同于上面链接的操作:
(1)创建服务端:进入解压后的文件夹目录D:\gsoap-2.8\gsoap\bin\win32下,可以看到两个exe文件。
编写接口文件itoa.h,在当前目录下运行shell命令: soapcpp2 -S itoa.h ,会生成好几个文件,更新后的目录如下:
在VS2015中新建工程,参考上面的链接替换itoaServer.cpp文件,在代码中替换两个语句,不然构建时会报错,方法如下:
运行服务端程序,将itoa.wsdl文件拷贝到debug目录下,shell命令行输入 .\itoaServer.exe 8087,在浏览器中打开对应网址,可以正常显示则服务端程序创建成功。
(2)建立客户端:
运行之前创建的服务端程序,回到D:\gsoap-2.8\gsoap\bin\win32下,删除之前生成的文件,shell命令行输入 wsdl2h -o itoa.h http://localhost:8087/itoa?Wsdl,会生成itoa.h文件,继续输入 soapcpp2 -j itoa.h,会生成代理类和相关文件。参照链接中的指导,在VS2015中新建客户端工程,编译并运行即可。
(3)这里附上服务端和客户端各自用到的文件和目录系统:
三、Qt5.9.4实现webService访问功能:
1. 访问上面创建的个人服务端:
(1)通过gsoap生成代理类和相关文件,操作和上面相同;
(2)Qt新建gui工程,导入相关文件,pro文件如下:
1 QT += gui widgets 2 3 CONFIG += c++11 4 #CONFIG += console 5 6 CONFIG -= app_bundle 7 8 DEFINES += QT_DEPRECATED_WARNINGS 9 10 SOURCES += main.cpp \11 soapC.cpp \12 soapitoaProxy.cpp \13 stdsoap2.cpp \14 dialog.cpp15 16 HEADERS += \17 # itoa.nsmap \18 soapitoaProxy.h \19 stdsoap2.h \20 soapH.h \21 soapStub.h \22 dialog.h23 24 FORMS += \25 dialog.ui
(3)ui布局:
(4)编写槽函数:
void Dialog::on_pushButton_clicked(){ itoaProxy service; double a, b; a = ui->lineEdit_a->text().toDouble(); b = ui->lineEdit_b->text().toDouble(); int connect_result; double add_res; connect_result = service.add( a, b, add_res ); qDebug( "%d %f", connect_result, add_res ); ui->lineEdit_addresult->setText( QString("%1").arg( add_res, 0, 'f', 2 ) );}
(5)注意事项:
导入相关文件后,直接编译会报错,截图如下:
错误原因是结构体重复定义,修改方法分三步:
-
注释部分代码:
-
将itoa.nsmap文件的部分代码拷贝到soapitoaProxy.cpp中:
-
注释itoa.nsmap头文件包含:
2. 访问已有的webService服务,以qq在线检测检测为例:
(1)web服务网址:
(2)生成qqCheckOnline.h头文件:
到D:\gsoap-2.8\gsoap\bin\win32目录下运行shell命令,输入
wsdl2h -o qqCheckOnline.h
(3)生成代理文件:
从D:\gsoap-2.8\gsoap\import目录下拷贝soap12.h文件,输入shell命令
soapcpp2 -j .\qqCheckOnline.h ,新的目录如下:
(4)Qt中新建gui工程,导入相关文件:
1 QT += core gui 2 3 CONFIG += c++11 4 CONFIG += console 5 6 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 7 8 TARGET = qqCheckOnline 9 TEMPLATE = app10 11 DEFINES += QT_DEPRECATED_WARNINGS12 13 SOURCES += \14 main.cpp \15 dialog.cpp \16 gsoap/soapC.cpp \17 gsoap/soapqqOnlineWebServiceSoapProxy.cpp \18 gsoap/stdsoap2.cpp19 20 HEADERS += \21 dialog.h \22 # gsoap/qqOnlineWebServiceSoap.nsmap \23 gsoap/soap12.h \24 gsoap/soapH.h \25 gsoap/soapqqOnlineWebServiceSoapProxy.h \26 gsoap/soapStub.h \27 gsoap/stdsoap2.h28 29 FORMS += \30 dialog.ui
(5)ui布局和槽函数编写:
void Dialog::on_pushButton_clicked(){ int connect_reult; std::string str_number, *str_state; str_number = ui->lineEdit_qq_number->text().toStdString(); qqOnlineWebServiceSoapProxy service; //使用代理类创建服务 _ns1__qqCheckOnline request; //函数调用需要的参数(包含qq号码) _ns1__qqCheckOnlineResponse response; //函数调用需要的参数(包含在线状态) qDebug( "%d", 111111 ); request.qqCode = &str_number; qDebug() << request.qqCode; connect_reult = service.qqCheckOnline( &request, response ); str_state = response.qqCheckOnlineResult; if( SOAP_OK != connect_reult ) { ui->lineEdit_qq_state->setText("soap连接失败"); return; } QString state = QString::fromStdString( *str_state ); if(state == "Y") { ui->lineEdit_qq_state->setText("在线"); } else if(state == "N") { ui->lineEdit_qq_state->setText("离线"); } else if(state == "E") { ui->lineEdit_qq_state->setText("QQ号码错误"); } else if(state == "A") { ui->lineEdit_qq_state->setText("商业用户验证失败"); } else if(state == "V") { ui->lineEdit_qq_state->setText("免费用户超过数量"); } else { ui->lineEdit_qq_state->setText("未知错误"); }}
(6)注释和拷贝gsoap/qqOnlineWebServiceSoap.nsmap的部分代码到soapqqOnlineWebServiceSoapProxy.cpp文件中:
(7)编译和运行结果图。
这个111111111111显示离线我是不信的,应该还没有12位的号吧,手动滑稽。
备注:如果编译或运行有别的问题,也可以一起讨论一下。ps:代码并不复杂,如果想要工程源码,可以私聊我。