Onvif开发之客户端搜索篇

简介: 关于ONVIF的广播,有客户端搜索和服务端发现的区别:客户端向固定的网段和固定的端口发送广播消息,服务端在对应的端口回复广播请求消息本文首先介绍客户端如何进行广播的已经对广播回复的信息的基本处理。 客户端这里处理相对服务端比较复杂一点,需要注意几个地方: 1 广播的ip和端口号(注意这个端口...

关于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函数登场了

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

运行测试结果如下图

              

 

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

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

目录
相关文章
|
6月前
|
Java
百度搜索:蓝易云【hutool Http 工具发送POST请求的几种方式。】
以上是使用Hutool发送POST请求的几种方式。根据实际需求和代码复杂度,选择合适的方式来发送POST请求。
184 0
|
7月前
|
网络协议 数据安全/隐私保护
百度搜索:蓝易云【WebSocket:从建立连接到关闭的完整流程】
这是WebSocket的基本流程,它提供了一种实时、双向的通信方式,适用于需要实时数据传输的应用场景,如聊天应用、实时游戏等。
203 2
|
8天前
|
缓存 数据库 索引
everything 本地文件搜索工具 完胜WIndows搜索 速度99% 超级给力
everything 本地文件搜索工具 完胜WIndows搜索 速度99% 超级给力
|
15天前
|
存储 数据库 数据安全/隐私保护
本地文件内容搜索神器AnyTXT Searcher如何搭建与远程访问
本地文件内容搜索神器AnyTXT Searcher如何搭建与远程访问
19 0
|
7月前
|
应用服务中间件 Apache PHP
百度搜索:蓝易云 ,什么是HTTP500内部服务器错误,要如何修复?
如果以上方法都没有解决问题,您可能需要进一步检查应用程序的代码、服务器环境和配置,并可能需要寻求专业人士的帮助。修复HTTP 500错误的过程可能因具体情况而异,因此建议根据具体情况进行调查和解决。
66 0
|
5月前
|
前端开发 JavaScript 应用服务中间件
百度搜索:蓝易云【服务器如何配置支持history模式】
配置完毕后,服务器将会将所有请求重定向到你的应用的index.html文件,使得history模式能够正常运行。这样,当用户在浏览器中直接访问子路径时,服务器会正确地返回index.html,并由前端路由接管处理。
64 1
|
5月前
|
安全 JavaScript 前端开发
百度搜索:蓝易云【webSocket的使用详解。】
通过按照上述步骤使用WebSocket,您可以在Web应用程序中实现实时的双向通信。请注意,在使用WebSocket时需要考虑安全性和网络性能等因素,并根据具体的应用场景进行适当的优化和安全设置。
35 0
|
5月前
|
网络协议 JavaScript 前端开发
百度搜索:蓝易云【WebSocket是什么,怎么用?】
综上所述,WebSocket是一种在Web浏览器和服务器之间实现双向通信的协议,通过创建WebSocket对象、处理WebSocket事件、发送和接收消息以及关闭连接来使用WebSocket。它提供了实时、持久且高效的通信方式,适用于各种实时应用场景。
37 7
|
7月前
|
JSON 数据格式 Python
百度搜索:蓝易云【Python数据使用HTTP代理教程!】
总结: 以上是使用Python进行数据请求时使用HTTP代理的简要教程。通过设置代理字典并将其传递给requests库的请求方法,你可以在Python中使用HTTP代理来发送和接收数据。请注意,代理的具体设置可能会因实际的代理类型和配置而有所不同。确保使用适当的代理地址和端口号,并根据代理提供商的要求进行设置。
28 1
|
7月前
|
Linux
百度搜索:蓝易云【linux系统切换IP实现HTTP代理教程。】
请注意,上述步骤是一个基本的教程,实际的设置可能因Linux发行版和网络环境而有所不同。确保在进行任何网络配置更改之前备份重要的数据,并在需要时咨询网络管理员或系统管理员的帮助。
39 3