自己调试OK的客户端discovery功能,discovery code,编译的时候,请修改脚本中的Path为自己gSoap所在的Path。
先从remotediscovery.wsdl解析入手吧。可以参考此网页WSDL实例解析 和 一个完整的WSDL文档及各标签详解。
1、命名空间
这个非常重要,直接导致是否可以调用到web server的功能函数。
1
|
<
wsdl:definitions
xmlns:dn
=
"http://www.onvif.org/ver10/network/wsdl"
xmlns:wsdl
=
"http://schemas.xmlsoap.org/wsdl/"
xmlns:soap
=
"http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:xs
=
"http://www.w3.org/2001/XMLSchema"
targetNamespace
=
"http://www.onvif.org/ver10/network/wsdl"
>
|
targetNamespace="http://www.onvif.org/ver10/network/wsdl",采用的命空间。
2、结构体定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<
wsdl:types
>
<
xs:schema
targetNamespace
=
"http://www.onvif.org/ver10/network/wsdl"
xmlns:d
=
"http://schemas.xmlsoap.org/ws/2005/04/discovery"
elementFormDefault
=
"qualified"
>
<
xs:import
namespace
=
"http://schemas.xmlsoap.org/ws/2005/04/discovery"
schemaLocation
=
"http://schemas.xmlsoap.org/ws/2005/04/discovery/ws-discovery.xsd"
/>
<!-- Message Request/Responses elements -->
<!--===============================-->
<
xs:element
name
=
"Hello"
type
=
"d:HelloType"
/>
<
xs:element
name
=
"HelloResponse"
type
=
"d:ResolveType"
/>
<
xs:element
name
=
"Probe"
type
=
"d:ProbeType"
/>
<
xs:element
name
=
"ProbeResponse"
type
=
"d:ProbeMatchesType"
/>
<
xs:element
name
=
"Bye"
type
=
"d:ByeType"
/>
<
xs:element
name
=
"ByeResponse"
type
=
"d:ResolveType"
/>
<!--===============================-->
</
xs:schema
>
</
wsdl:types
>
|
schemaLocation="http://schemas.xmlsoap.org/ws/2005/04/discovery/ws-discovery.xsd"/,进入/ws-discovery.xsd可以看到
1
2
3
4
5
6
7
8
|
<
xs:complexType
name
=
"ProbeType"
>
<
xs:sequence
>
<
xs:element
ref
=
"tns:Types"
minOccurs
=
"0"
/>
<
xs:element
ref
=
"tns:Scopes"
minOccurs
=
"0"
/>
<
xs:any
namespace
=
"##other"
processContents
=
"lax"
minOccurs
=
"0"
maxOccurs
=
"unbounded"
/>
</
xs:sequence
>
<
xs:anyAttribute
namespace
=
"##other"
processContents
=
"lax"
/>
</xs:complexType
|
code中对应的为,命名由 <
xs:element
name
=
"Probe"
type
=
"d:ProbeType"
/> 中的
type
=
"d:ProbeType"
而来
1
2
3
4
5
6
7
8
9
10
11
12
|
#ifndef SOAP_TYPE_d__ProbeType
#define SOAP_TYPE_d__ProbeType (290)
/* d:ProbeType */
struct
d__ProbeType
{
char
**Types;
/* optional element of type xsd:QName */
struct
d__ScopesType *Scopes;
/* optional element of type d:ScopesType */
int
__size;
/* sequence of elements <-any> */
char
**__any;
char
*__anyAttribute;
/* optional attribute of type xsd:anyType */
};
#endif
|
3、参数
1
2
3
4
|
</
wsdl:message
>
<
wsdl:message
name
=
"ProbeRequest"
>
<
wsdl:part
name
=
"parameters"
element
=
"dn:Probe"
/>
</
wsdl:message
>
|
<
wsdl:part
name
=
"parameters"
element
=
"dn:Probe"
/> 表明使用的是
<
xs:element
name
=
"Probe"
type
=
"d:ProbeType"
/>,也即为
struct
d__ProbeType。
4、函数体
1
2
3
4
5
6
|
<
wsdl:portType
name
=
"DiscoveryLookupPort"
>
<
wsdl:operation
name
=
"Probe"
>
<
wsdl:input
message
=
"dn:ProbeRequest"
dn:Action
=
"http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"
/>
<
wsdl:output
message
=
"dn:ProbeResponse"
dn:Action
=
"http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches"
/>
</
wsdl:operation
>
</
wsdl:portType
>
|
这个 dn:Action
=
"http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"
望文生义是关于Probe()的,具体
不知道什么意义,也没有找到此页面。知道的同学请告知。
客户端:
SOAP_FMAC5 int SOAP_FMAC6 soap_call___d__Probe(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct d__ProbeType *d__Probe, struct d__ProbeMatchesType *d__ProbeMatches)
此soap_call___d__Probe(和soap_serve___d__Probe交互)可以调用用web server的Probe功能。
服务端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
/*
soap_serve --> soap_serve_request --> soap_serve___d__Probe --> sever_probe
*/
int
main(
int
argc,
char
**argv)
{
int
m, s;
struct
soap add_soap;
soap_init(&add_soap);
soap_set_namespaces(&add_soap, namespaces);
if
(argc < 2) {
printf
(
"usage: %s <server_port> \n"
, argv[0]);
exit
(1);
}
else
{
m = soap_bind(&add_soap, NULL,
atoi
(argv[1]), 100);
if
(m < 0) {
soap_print_fault(&add_soap, stderr);
exit
(-1);
}
fprintf
(stderr,
"Socket connection successful: master socket = %d\n"
, m);
for
(;;) {
s = soap_accept(&add_soap);
if
(s < 0) {
soap_print_fault(&add_soap, stderr);
exit
(-1);
}
fprintf
(stderr,
"Socket connection successful: slave socket = %d\n"
, s);
soap_serve(&add_soap);
soap_end(&add_soap);
}
}
return
0;
}
SOAP_FMAC5
int
SOAP_FMAC6 soap_serve(
struct
soap *soap)
{
#ifndef WITH_FASTCGI
unsigned
int
k = soap->max_keep_alive;
#endif
do
{
#ifndef WITH_FASTCGI
if
(soap->max_keep_alive > 0 && !--k)
soap->keep_alive = 0;
#endif
if
(soap_begin_serve(soap))
{
if
(soap->error >= SOAP_STOP)
continue
;
return
soap->error;
}
if
(soap_serve_request(soap) || (soap->fserveloop && soap->fserveloop(soap)))
{
#ifdef WITH_FASTCGI
soap_send_fault(soap);
#else
return
soap_send_fault(soap);
#endif
}
#ifdef WITH_FASTCGI
soap_destroy(soap);
soap_end(soap);
}
while
(1);
#else
}
while
(soap->keep_alive);
#endif
return
SOAP_OK;
}
SOAP_FMAC5
int
SOAP_FMAC6 soap_serve_request(
struct
soap *soap)
{
soap_peek_element(soap);
if
(!soap_match_tag(soap, soap->tag,
"SOAP-ENV:Fault"
))
return
soap_serve_SOAP_ENV__Fault(soap);
if
(!soap_match_tag(soap, soap->tag,
"d:Hello"
))
return
soap_serve___d__Hello(soap);
if
(!soap_match_tag(soap, soap->tag,
"d:Bye"
))
return
soap_serve___d__Bye(soap);
if
(!soap_match_tag(soap, soap->tag,
"d:Probe"
))
return
soap_serve___d__Probe(soap);
......
}
soap_serve___d__Probe
{
sever_probe();
}
|
5、绑定
这个就是wsdl和soap的结合了。前面的理解没问题的话,这部分就不用关心了。
调通了discovery,只是一个良好的开端。后续还有一堆事情要解决。待续。
6、其他
最后采用的代码是soap_send___wsdd__Probe/soap_recv___wsdd__ProbeMatches,空间不同而已。换用soap_send___wsdd__Probe的时候,出了一个小BUG:设定的timeout 似乎对soap_recv___wsdd__ProbeMatches无效。经排查对比,发现是gsoap版本的差异。
while (result == SOAP_OK)
{
//gsoap2.8.17 block, gsoap2.8.1.10 timeout enable
result = soap_recv___wsdd__ProbeMatches(psoap, &res);
}