关于ONVIF的广播,有客户端搜索和服务端发现的区别:客户端向固定的网段和固定的端口发送广播消息,服务端在对应的端口回复广播请求消息
本文首先介绍客户端如何进行广播的已经对广播回复的信息的基本处理。

客户端这里处理相对服务端比较复杂一点,需要注意几个地方:

1 广播的ip和端口号(注意这个端口号和通信的端口是不一样的,通信端口号可以自己随意定一个,但是这个广播的是ONVIF协议定好公用的)

ip:239:255:255:250   port:3702

2 MessageID ,此ID每次都需要不同,不然每次只有第一次能搜索到设备,第二次就不行了!一般情况下都是区uuid的随机值的,但是我在开发的过程是去的一个随机值加上自己设备的mac地址组合的

3 soap_send___wsdd__Probe函数,发送广播信息,通过它来判断是否发送成功,确认是否继续下一步操作进行接收消息

4 soap_recv___wsdd__ProbeMatches函数,此函数是通过广播后,设备通过onvif协议回复了设备的一些基本信息,客户端通过循 环调用此函数来接多个设备回复的各个设备的一些基本信息包括设备ip以及通信的prot

知道了这几个基本的注意点和前篇介绍的代码生成框架,接下来就是敲代码了。该main函数登场了

  1. <span style="font-size:14px;">/*
  2. * =====================================================================================
  3. *
  4. *       Filename:  main.c
  5. *    Description:  简单例程测试:客户端通过ONVIF协议搜索前端设备,
  6. *        Created:  2013年12月26日 12时17分48秒
  7. *       Compiler:  gcc
  8. *         Author:  max_min_,
  9. *
  10. * =====================================================================================
  11. */
  12. #include "wsdd.h"
  13. #include <stdio.h>
  14. static struct soap* ONVIF_Initsoap(struct SOAP_ENV__Header *header, const char *was_To, const char *was_Action, int timeout)
  15. {
  16. struct soap *soap = NULL;
  17. unsigned char macaddr[6];
  18. char _HwId[1024];
  19. unsigned int Flagrand;
  20. soap = soap_new();
  21. if(soap == NULL)
  22. {
  23. printf("[%d]soap = NULL\n", __LINE__);
  24. return NULL;
  25. }
  26. soap_set_namespaces( soap, namespaces);
  27. //超过5秒钟没有数据就退出
  28. if (timeout > 0)
  29. {
  30. soap->recv_timeout = timeout;
  31. soap->send_timeout = timeout;
  32. soap->connect_timeout = timeout;
  33. }
  34. else
  35. {
  36. //如果外部接口没有设备默认超时时间的话,我这里给了一个默认值10s
  37. soap->recv_timeout    = 10;
  38. soap->send_timeout    = 10;
  39. soap->connect_timeout = 10;
  40. }
  41. soap_default_SOAP_ENV__Header(soap, header);
  42. // 为了保证每次搜索的时候MessageID都是不相同的!因为简单,直接取了随机值
  43. srand((int)time(0));
  44. Flagrand = rand()%9000 + 1000; //保证四位整数
  45. macaddr[0] = 0x1; macaddr[1] = 0x2; macaddr[2] = 0x3; macaddr[3] = 0x4; macaddr[4] = 0x5; macaddr[5] = 0x6;
  46. sprintf(_HwId,"urn:uuid:%ud68a-1dd2-11b2-a105-%02X%02X%02X%02X%02X%02X",
  47. Flagrand, macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
  48. header->wsa__MessageID =(char *)malloc( 100);
  49. memset(header->wsa__MessageID, 0, 100);
  50. strncpy(header->wsa__MessageID, _HwId, strlen(_HwId));
  51. if (was_Action != NULL)
  52. {
  53. header->wsa__Action =(char *)malloc(1024);
  54. memset(header->wsa__Action, '\0', 1024);
  55. strncpy(header->wsa__Action, was_Action, 1024);//"http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";
  56. }
  57. if (was_To != NULL)
  58. {
  59. header->wsa__To =(char *)malloc(1024);
  60. memset(header->wsa__To, '\0', 1024);
  61. strncpy(header->wsa__To,  was_To, 1024);//"urn:schemas-xmlsoap-org:ws:2005:04:discovery";
  62. }
  63. soap->header = header;
  64. return soap;
  65. }
  66. int ONVIF_ClientDiscovery( )
  67. {
  68. int HasDev = 0;
  69. int retval = SOAP_OK;
  70. wsdd__ProbeType req;
  71. struct __wsdd__ProbeMatches resp;
  72. wsdd__ScopesType sScope;
  73. struct SOAP_ENV__Header header;
  74. struct soap* soap;
  75. const char *was_To = "urn:schemas-xmlsoap-org:ws:2005:04:discovery";
  76. const char *was_Action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";
  77. //这个就是传递过去的组播的ip地址和对应的端口发送广播信息
  78. const char *soap_endpoint = "soap.udp://239.255.255.250:3702/";
  79. //这个接口填充一些信息并new返回一个soap对象,本来可以不用额外接口,
  80. // 但是后期会作其他操作,此部分剔除出来后面的操作就相对简单了,只是调用接口就好
  81. soap = ONVIF_Initsoap(&header, was_To, was_Action, 5);
  82. soap_default_SOAP_ENV__Header(soap, &header);
  83. soap->header = &header;
  84. soap_default_wsdd__ScopesType(soap, &sScope);
  85. sScope.__item = "";
  86. soap_default_wsdd__ProbeType(soap, &req);
  87. req.Scopes = &sScope;
  88. req.Types = ""; //"dn:NetworkVideoTransmitter";
  89. retval = soap_send___wsdd__Probe(soap, soap_endpoint, NULL, &req);
  90. //发送组播消息成功后,开始循环接收各位设备发送过来的消息
  91. while (retval == SOAP_OK)
  92. {
  93. retval = soap_recv___wsdd__ProbeMatches(soap, &resp);
  94. if (retval == SOAP_OK)
  95. {
  96. if (soap->error)
  97. {
  98. printf("[%d]: recv error:%d,%s,%s\n", __LINE__, soap->error, *soap_faultcode(soap), *soap_faultstring(soap));
  99. retval = soap->error;
  100. }
  101. else //成功接收某一个设备的消息
  102. {
  103. HasDev ++;
  104. if (resp.wsdd__ProbeMatches->ProbeMatch != NULL && resp.wsdd__ProbeMatches->ProbeMatch->XAddrs != NULL)
  105. {
  106. printf(" ################  recv  %d devices info #### \n", HasDev );
  107. printf("Target Service Address  : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->XAddrs);
  108. printf("Target EP Address       : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address);
  109. printf("Target Type             : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->Types);
  110. printf("Target Metadata Version : %d\r\n", resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion);
  111. sleep(1);
  112. }
  113. }
  114. }
  115. else if (soap->error)
  116. {
  117. if (HasDev == 0)
  118. {
  119. printf("[%s][%d] Thers Device discovery or soap error: %d, %s, %s \n", __func__, __LINE__, soap->error, *soap_faultcode(soap), *soap_faultstrin
  120. retval = soap->error;
  121. }
  122. else
  123. {
  124. printf(" [%s]-[%d] Search end! It has Searched %d devices! \n", __func__, __LINE__, HasDev);
  125. retval = 0;
  126. }
  127. break;
  128. }
  129. }
  130. soap_destroy(soap);
  131. soap_end(soap);
  132. soap_free(soap);
  133. return retval;
  134. }
  135. int main(void )
  136. {
  137. //组播接口
  138. if (ONVIF_ClientDiscovery() != 0 )
  139. {
  140. printf("discovery failed!\n");
  141. return -1;
  142. }
  143. return 0;
  144. }
  145. </span>

运行测试结果如下图

可以看到注意信息就是http://172.18.13.127:9000/onvif/device_service这句了!设备的IP地址以及通信端口都有了,第三个没有端口,也就是使用默认的端口80了,海康和大华的貌似都是用80端口
到这里差不多客户端的搜索就完成了,剩下只是把搜索到的设备信息解析出来,然后保存起来!提供给客户端使用了,我在实际开发的过程中是通过调用外层接口传递一个回调函数指针进去,然后匹配信息出来,给客户端!

搜索使用的源码下载地址:onvif客户端搜索

Onvif开发之客户端搜索篇的更多相关文章

  1. Onvif开发之客户端鉴权获取参数篇

    前面一篇已经介绍了客户端如何发些设备,下面这篇简单介绍下在发现设备后,如何通过ONVIF协议来获取设备的相关参数 ONVIF中不管是客户端还是设备端,最先实现的接口都是关于能力的那个接口,在客户端实现 ...

  2. Jsoup开发网站客户端第二篇,图片轮播,ScrollView兼容ListView

    最近一段日子忙的焦头烂额,代码重构,新项目编码,导致jsoup开发网站客户端也没时间继续下去,只能利用晚上时间去研究了.今天实现美食网首页图片轮播效果,网站效果图跟Android客户端实现如图: 从浏 ...

  3. Onvif开发之基础介绍篇

    什么是Onvif协议,谁开启了Onvif时代? ONVIF:原意为 开放型网络视频接口论坛,即 Open Network Video Interface Forum ,是安讯士.博世.索尼等三家公司在 ...

  4. ONVIF客户端搜索设备获取rtsp地址开发笔记(精华篇)

    原文  http://blog.csdn.net/gubenpeiyuan/article/details/25618177   概要: 目前ONVIF协议家族设备已占据数字监控行业半壁江山以上,亲, ...

  5. 【视频开发】ONVIF客户端搜索设备获取rtsp地址开发笔记(精华篇)

    转载地址:http://blog.csdn.net/gubenpeiyuan/article/details/25618177 概要:           目前ONVIF协议家族设备已占据数字监控行业 ...

  6. onvif开发之设备发现功能的实现--转

    忙了一个多月,onvif总算告一段落了.这几个星期忙着其他的项目,也没有好好整理一下onvif的东西.接下来得好好整理一下自己的项目思路和项目经验,同时将自己的一些心得写出来,希望对人有所帮助. 相信 ...

  7. Python开发【第二十一篇】:Web框架之Django【基础】

    Python开发[第二十一篇]:Web框架之Django[基础]   猛击这里:http://www.cnblogs.com/wupeiqi/articles/5237704.html Python之 ...

  8. Python开发【第二十篇】:缓存

    Python开发[第二十篇]:缓存redis&Memcache   点击这里 Python之路[第九篇]:Python操作 RabbitMQ.Redis.Memcache.SQLAlchemy ...

  9. Struts 2.x仍然明显落后于时代。 Struts 2.x这一类老牌Web MVC开发框架仅能用于开发瘦客户端应用,无法用来开发对于交互体验要求更高的应用。

    后来我在工作中陆续使用过Struts 1.x和Struts 2.x.我曾经把一个开源的基于Struts 1.x的自助式广告联盟应用移植到Spring MVC,还基于Struts 2.x做过网站开发.S ...

随机推荐

  1. jquery的append/prepend和after/before有什么区别呢?

    append <p> <span class="s1">s1</span> </p> <script> $(" ...

  2. atom玩法

    1.先用 git 下载一个 react-devtools: $ cd /some-directory$ git clone --recursive https://github.com/faceboo ...

  3. spring context对象

    在 java 中, 常见的 Context 有很多, 像: ServletContext, ActionContext, ServletActionContext, ApplicationContex ...

  4. Java ——代理模式[转发]

    1.  简介 代理模式(Proxy Pattern)是GoF 23种Java常用设计模式之一.代理模式的定义:Provide a surrogate or placeholder for anothe ...

  5. Hope is a good thing, maybe the best of things and no good thing ever dies !

  6. 洛谷3964 [TJOI2013]松鼠聚会

    题目描述 草原上住着一群小松鼠,每个小松鼠都有一个家.时间长了,大家觉得应该聚一聚.但是草原非常大,松鼠们都很头疼应该在谁家聚会才最合理. 每个小松鼠的家可以用一个点x,y表示,两个点的距离定义为点( ...

  7. Centos7不修改默认交换分区下添加交换分区

    交换分区介绍 Linux系统中的交换分区是当物理内存(RAM)被充满时,作为物理内存的缓存来使用. 当系统需要更多的内存资源而物理内存已经充满,内存中不活跃的页就会被移动到交换分区上. 交换分区位于硬 ...

  8. Linux Network配置

    /etc/sysconfig/network [root@mytest ~]# cat /etc/sysconfig/network NETWORKING=yes HOSTNAME=mytest /e ...

  9. ifreq、ifconf

    网络相关的ioctl请求的request参数及arg地址必须指向的数据类型如下表所示: 接口 SIOCGIFCONF SIOCSIFADDR SIOCGIFADDR SIOCSIFBRDADDR SI ...

  10. 【Uva 11400】Lighting System Design

    [Link]: [Description] 你要构建一个供电系统; 给你n种灯泡来构建这么一个系统; 每种灯泡有4个参数 1.灯泡的工作电压 2.灯泡的所需的电源的花费(只要买一个电源就能供这种灯泡的 ...