头文件Netinterface.h如下:
struct ns__ipAddr
{
char *ns__ip;
int ns__index;
};
struct ns__ipTable
{
};
struct ns__ipTableResponse
{
struct ns__ipAddr *__ptr;
int __size;
};
int ns__getIpTable(struct ns__ipTable *ipTab_In, struct ns__ipTableResponse* ipTable_Out);
接口为ns__getIpTable, 第一个形参为输入(相对Server而言,下同),第二个形参为输出结构体。
结构体ns__ipTableResponse内成员一定要是__ptr, 并且要指定__size,它们前面都不能加命名空间,加了后用soapcpp2生成的代码是有问题的,无法完成多个结构体传送的目的,这个事情折腾了很久,尽管在网上能找到一些答案,当时成员类型是一样的,但成员名却跟这个不一样,浪费了两天多时间,这也算是自负的后果吧。 所以一定记得要用上一样的成员名,这个估计是生成器能识别到的名字,它是根据这个来生成结构的。
具体有何不同呢? 可以试着把成员名__ptr改成ns__ptr, 你再去看看生成的soapStub.h里有没有这个结构体? 怕是没有吧!
#ifndef SOAP_TYPE_ns__getIpTableResponse
#define SOAP_TYPE_ns__getIpTableResponse (20)
/* ns:getIpTableResponse */
struct ns__getIpTableResponse
{
struct ns__ipTableResponse *ipTable_Out; /* SOAP 1.2 RPC return element (when namespace qualified) */ /* optional element of type ns:ipTableResponse */
};
#endif
找到soapcpp2执行文件,新建一个工程目录后进入,在terminal里执行$ ./soapcpp2 -c Netinterface.h
-c 是生成纯C的SOAP代码架构的意思,这些可以参看soapcpp2命令说明。 OK,生成架构后即可开始码代码了。
Server端:
下面的目录文件ipaddr内容为:
10.0.0.234
10.0.0.235
10.0.0.236
10.0.0.237
#define myTable "/etc/ipaddr"
#define IP_LEN 4
#define IP_BUF 100
#define IPADDR_LEN 16
int getIpInfoBySys()
{
int i=0;
FILE *fp_ipaddr;
fp_ipaddr = fopen(myTable, "r");
if(fp_ipaddr == NULL)
{
printf("error\n");
return -1;
}
char line[IP_BUF];
while(!feof(fp_ipaddr))
{
memset(strIP[i], '\0', IP_BUF);
memset(line, '\0', IP_BUF);
fgets(line, sizeof(line), fp_ipaddr);
line[strlen(line)-1] = '\0';
sprintf(strIP[i], "%s", line);
i++;
if(i > IP_LEN-1)
break;
}
fclose(fp_ipaddr);
fp_ipaddr = NULL;
return 0;
}
int
main (int argc, char *argv[])
{
int m, s;
struct soap mySoap;
soap_init (&mySoap);
mySoap.bind_flags = SO_REUSEADDR;
mySoap.fget = http_get;
soap_set_namespaces(&mySoap, namespaces);
soap_set_recv_logfile(&mySoap, "./log/S_RECV.log");
soap_set_sent_logfile(&mySoap, "./log/S_SENT.log");
soap_set_test_logfile(&mySoap, "./log/S_TEST.log");
if (argc < 2)
{
printf ("usage: %s <server_port> \n", argv[0]);
exit (1);
}
else
{
m = soap_bind (&mySoap, NULL, atoi (argv[1]), 100);
if (m < 0)
{
soap_print_fault (&mySoap, stderr);
exit (-1);
}
fprintf (stderr, "Socket connection successful: master socket = %d\n",m);
for (;;)
{
s = soap_accept (&mySoap);
if (s < 0)
{
soap_print_fault (&mySoap, stderr);
exit (-1);
}
fprintf (stderr,
"Socket connection successful: slave socket = %d\n", s);
soap_serve (&mySoap); //该句说明该server的服务
soap_end (&mySoap);
}
}
return 0;
}
int
ns__getIpTable(struct soap *mySoap, struct ns__ipTable *ipTab_In, struct ns__ipTableResponse* ipTable_Out)
{
if(getIpInfoBySys() != 0)
{
printf("getIpInfoBySys failed\n");
return -1;
}
ipTable_Out->__size = 4;
struct ns__ipAddr * myIpAddr = (struct ns__ipAddr *)soap_malloc(mySoap, ipTable_Out->__size * sizeof(struct ns__ipAddr));
ipTable_Out->__ptr = myIpAddr;
int i=0;
for(i=0; i<ipTable_Out->__size; i++)
{
myIpAddr[i].ns__index = i;
myIpAddr[i].ns__ip = (char *)soap_malloc(mySoap, IPADDR_LEN);
memset(myIpAddr[i].ns__ip, '\0', IPADDR_LEN);
strncpy(myIpAddr[i].ns__ip, strIP[i], IPADDR_LEN);
printf("%d--%s\n", myIpAddr[i].ns__index, myIpAddr[i].ns__ip);
}
return 0;
}
Client端:
/****************Main********************/
struct ns__ipTableResponse ipTable;
result = getIpTable (server, "", &ipTable);
if (result != 0)
{
printf ("getIpTable failed\n");
}
/************************************/
int
getIpTable (const char *server, struct ns__ipTable *ipTab_In, struct ns__ipTableResponse* ipTable_Out)
{
struct soap mySoap; /* 创建mySoap()结构体 */
int result = 0;
soap_init (&mySoap); /* soap_init()*/
soap_set_namespaces(&mySoap, namespaces);
#ifdef __DEBUG
soap_set_recv_logfile(&mySoap, "./log/C_RECV.log");
soap_set_sent_logfile(&mySoap, "./log/C_SENT.log");
soap_set_test_logfile(&mySoap, "./log/C_TEST.log");
#endif
soap_call_ns__getIpTable (&mySoap, server, "", ipTab_In, ipTable_Out); /* 调用soap_call_ns__getIpTable() */
if (mySoap.error)
{
printf ("soap error:%d,%s,%s\n", mySoap.error,
*soap_faultcode (&mySoap), *soap_faultstring (&mySoap));
result = mySoap.error;
}
else
{
printf ("size of IPaddr is %d\n", ipTable_Out->__size);
int cnt=0;
for(cnt = 0; cnt < ipTable_Out->__size; cnt++)
{
printf("index--%d, IpAddress is %s\n", (ipTable_Out->__ptr + cnt)->ns__index, (ipTable_Out->__ptr + cnt)->ns__ip);
}
}
soap_end (&mySoap); /* 释放内存空间 */
soap_done (&mySoap);
return result;
}
最后,分别执行Server及Client端应用即可。
PS: 要善于利用wireshark网络抓包工具,对协议包进行分析,另外也要会用gsoap提供的debug log, 从里面可以看出很多问题。 我的一个内存出错问题还有结构体传送异常问题也都是通过它找到答案的。