欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

动环监控系统中B接口的实现-c语言版

程序员文章站 2022-07-14 17:06:18
...

B接口是使用http+xml+ftp形成的一套通讯框架,一般使用gsoap库来开发

首先是准备gsoap库,编译方法这里就不细说了,这里稍微说下用法
开发环境是ubuntu 64位,测试环境是也是ubuntu64位
gsoap 用的是2.8.22
编译完成后,会生成wsdl2h,soapcpp2两个应用程序

动环监控官方给了我两个wsdl文件,分别是客户端和服务端的
FSUService.wsdl
LSCService.wsdl

这里只说设备端怎么做,如果想知道其它,欢迎留言

1.使用wsdl2h工具,根据WSDL产生头文件FSUService.h,执行以下命令
wsdl2h -c -s FSUService.wsdl
-c为产生纯c代码
-s为不使用STL库
详情可通过wsdl2h.exe -help查看帮助。

2.使用soapcpp2工具,根据头文件 FSUService.h 产生框架代码,执行以下命令
soapcpp2 -2 -c FSUService.h
-2 生成 SOAP 1.2
-c 为产生纯c代码,默认生成 c++代码

这有个小细节,要注意gsoap库的版本,前后端不一致就会有问题

将生成的文件复制到自己的工程
soapClient.c
soapH.h
soapServer.c
LSCServiceSoapBinding.nsmap
soapStub.h

写一个server.c作为服务端

#include "soapH.h"
#include "stdsoap2.h"
#include "FSUServiceSoapBinding.nsmap"
int main()
{
 		SOAP_SOCKET master,slave;
    	struct soap *soap=soap_new();
    	soap->send_timeout=5;
    	soap_set_namespaces(soap,namespaces);//之前看到某个教程服务端竟然没写,经过实验证明,不加就是找死
    	soap->bind_flags|=SO_REUSEADDR;// 这里有个bug,绑定的时候竟然没有使用地址重绑定,如果反复启动几回就会出现绑定失败的情况,这句话是通过源码分析得出的使用方法
        master=soap_bind(soap,NULL,30376,100);
    	while(1)
    	{
        		slave=soap_accept(soap);
        		if(slave<0)
       			{
            		continue;
        		}
        		soap_serve(soap);
        		soap_end(soap);
    	}
    	soap_destroy(soap);
    	soap_done(soap);
    	free(soap);
}
//下面这坨是我自己的业务代码
SOAP_FMAC5 int SOAP_FMAC6 ns1__invoke(struct soap *soap, char *_xmlData, char **_invokeReturn)
{
    *_invokeReturn="ooxx";
    return SOAP_OK;
}
    ```

下面是客户端client.c的代码,一看就知道是抄别人的,没办法,懒嘛,不过我可是加工过的

int main(int argc, char **argv)
{

struct soap *fsuSoap = soap_new();
fsuSoap->send_timeout = fsuSoap->recv_timeout = 5;    
struct ns1__invokeResponse soap_tmp_ns1__invokeResponse;
char * soap_tmp_SOAP_ENC__string;
soap_default_ns1__invokeResponse(fsuSoap, &soap_tmp_ns1__invokeResponse);
soap_tmp_SOAP_ENC__string = NULL;
soap_tmp_ns1__invokeResponse._invokeReturn = &soap_tmp_SOAP_ENC__string;

char xmlData[500];
memset(xmlData, 0x00, sizeof(xmlData));
strcat(xmlData, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
strcat(xmlData, "<Request>\n");
strcat(xmlData, "<PK_Type>\n");
strcat(xmlData, "<Name>GET_DATA</Name>\n");
strcat(xmlData, "</PK_Type>\n");
strcat(xmlData, "<Info>\n");
strcat(xmlData, "<FSUID/>\n");
strcat(xmlData, "<DeviceList>\n");
strcat(xmlData, "<Device ID=\"303\">\n");
strcat(xmlData, "</Device>\n");
strcat(xmlData, "</DeviceList>\n");
strcat(xmlData, "</Info>\n");
strcat(xmlData, "</Request>\n");

printf("soap_tmp_ns1__invoke._xmlData:\n");
printf("%s", xmlData);
int iRet = soap_call_ns1__invoke(fsuSoap, NULL, NULL, xmlData, 	                soap_tmp_ns1__invokeResponse._invokeReturn);
if ( iRet == SOAP_ERR)
{
    printf("Error while calling the soap_call_ns1__invoke");
}
else
{
     //这里有个坑,如果程序的xml有问题是会返回500的,如果连接异常是会返回28的,如果namespace异常就是SOAP_CLI_FAULT,这鬼demo也是没谁了,这里我只能判断_invokeReturn不为空才是正经回复
    printf("Calling the soap_call_ns1__invoke success?ret=%d\n",iRet);
    if(*soap_tmp_ns1__invokeResponse._invokeReturn
    	printf("%s\n", *soap_tmp_ns1__invokeResponse._invokeReturn);
}

return 0;

}

客户端和服务端编译就是这么简单
gcc client.c soapC.c soapClient.c -lgsoap -o client
gcc server.c soapC.c soapServer.c -lgsoap -o server

流程就是这么个流程,但是

服务端收不到呀,经过排查发现,soapClient.c发送的时候会带一个SOAP-ENV:Body这样的鬼玩意,服务端则是判断有没有ns__invoke这个字段,就是说发送的xml对于接收端来说,是异端,由于代码是自动生成的,所以还需要修改下soapClient.c
找到这一对代码并删除,就可以了,具体是哪一对嘛,就是connect下面的,我比较懒,就不细说了,聪明的你一看就能明白,蠢笨如我是讲不明白的
soap_body_begin_out(soap)
soap_body_end_out(soap)