一、设备发现的机制

从ONVIF的官方文档中可以了解到,客户端在UDP协议下,向网段内的组播地址239.255.255.250,端口3702,不断地向四周发送Probe消息探针,而网段内的服务器在接收到Probe这个探测消息后,通过回复ProbeMatch消息让客户端接收,从而让客户端识别到服务器。

所以服务器端就需要创建一个UDP协议的socket,去监听239.255.255.250:3702,接收到客户端的Probe探针后,进行响应,从而让客户端识别到onvif服务器。


二、编程环境

1. onvif服务器框架代码

服务器的框架代码在上一篇博客中已经实现,详情可以参考《onvif服务器篇之onvif 服务器框架的搭建》。

2.onvifServerInterface.c接口函数

在框架代码的基础上,我们需要创建一个onvifServerInterface.c文件,去实现一些接口函数,这些接口函数来自于各个wsdl文件对应模块的接口,但是这些接口需要我们自己去实现,这是ONVIF的实现机制,哪怕没有调用到,也要给一个空函数体,这一点在《onvif服务器篇之onvif 服务器框架的搭建》最后一段中有交代。

3.main.c主函数

main.c实现的功能是在用来建立socket去监听239.255.255.250,端口3702,这里在前面设备发现的机制中已经有提到。


三、代码实现

1.onvifServerInterface.c的实现

#include "wsaapi.h"
#include "soapH.h"
#include "soapStub.h"
#include "wsdd.nsmap"SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Hello(struct soap* soap, struct wsdd__HelloType *wsdd__Hello)
{return 0;
}SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Bye(struct soap* soap, struct wsdd__ByeType *wsdd__Bye)
{return 0;
}SOAP_FMAC5 int SOAP_FMAC6 __wsdd__ProbeMatches(struct soap* soap, struct wsdd__ProbeMatchesType *wsdd__ProbeMatches)
{return 0;
}SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Resolve(struct soap* soap, struct wsdd__ResolveType *wsdd__Resolve)
{return 0;
}SOAP_FMAC5 int SOAP_FMAC6 __wsdd__ResolveMatches(struct soap* soap, struct wsdd__ResolveMatchesType *wsdd__ResolveMatches)
{return 0;
}#define IP 192.168.20.1                    //服务器IP
#define ONVIF_TCP_PORT 5000             //服务器访问端口(随意设置)SOAP_FMAC5 int SOAP_FMAC6  __wsdd__Probe(struct soap* soap, struct wsdd__ProbeType *wsdd__Probe)
{char scopes_message[] ="onvif://www.onvif.org/type/NetworkVideoTransmitter\r\n""onvif://www.onvif.org/Profile/Streaming\r\n""onvif://www.onvif.org/Profile/Q/Operational\r\n""onvif://www.onvif.org/hardware/HD1080P\r\n""onvif://www.onvif.org/name/discover_test\r\n""onvif://www.onvif.org/location/city/GuangZhou\r\n""onvif://www.onvif.org/location/country/China\r\n";// response ProbeMatchesstruct wsdd__ProbeMatchesType   wsdd__ProbeMatches = {0};struct wsdd__ProbeMatchType     *pProbeMatchType = NULL;struct wsa__Relationship        *pWsa__RelatesTo = NULL;pProbeMatchType = (struct wsdd__ProbeMatchType*)soap_malloc(soap, sizeof(struct wsdd__ProbeMatchType));soap_default_wsdd__ProbeMatchType(soap, pProbeMatchType);char str_tmp[256] = {0};sprintf(str_tmp, "http://%s:%d/onvif/device_service", IP, ONVIF_TCP_PORT);pProbeMatchType->XAddrs = soap_strdup(soap, str_tmp);if( wsdd__Probe->Types && strlen(wsdd__Probe->Types) )pProbeMatchType->Types  = soap_strdup(soap, wsdd__Probe->Types);elsepProbeMatchType->Types  = soap_strdup(soap, "dn:NetworkVideoTransmitter tds:Device");pProbeMatchType->MetadataVersion = 1;// Build Scopes Messagestruct wsdd__ScopesType *pScopes = NULL;pScopes = (struct wsdd__ScopesType *)soap_malloc(soap, sizeof(struct wsdd__ScopesType));soap_default_wsdd__ScopesType(soap, pScopes);pScopes->MatchBy = NULL;pScopes->__item  = soap_strdup(soap, scopes_message);pProbeMatchType->Scopes = pScopes;char g_uuid[64];snprintf(g_uuid, 64, "%s", soap_wsa_rand_uuid(soap));pProbeMatchType->wsa__EndpointReference.Address = soap_strdup(soap, g_uuid);wsdd__ProbeMatches.__sizeProbeMatch = 1;wsdd__ProbeMatches.ProbeMatch       = pProbeMatchType;// Build SOAP HeaderpWsa__RelatesTo = (struct wsa__Relationship*)soap_malloc(soap, sizeof(struct wsa__Relationship));soap_default__wsa__RelatesTo(soap, pWsa__RelatesTo);pWsa__RelatesTo->__item = soap->header->wsa__MessageID;soap->header->wsa__RelatesTo = pWsa__RelatesTo;soap->header->wsa__Action      = soap_strdup(soap, "http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches");soap->header->wsa__To          = soap_strdup(soap, "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous");soap_send___wsdd__ProbeMatches(soap, "http://", NULL, &wsdd__ProbeMatches);return SOAP_OK;
}

2.main.c的实现

#include "soapH.h"#define ONVIF_UDP_IP "239.255.255.250"
#define ONVIF_UDP_PORT 3702//绑定端口
static SOAP_SOCKET SoapBind(struct soap *pSoap, const char *pIp, bool flag)
{SOAP_SOCKET sockFD = SOAP_INVALID_SOCKET;if (flag){sockFD = soap_bind(pSoap, ONVIF_UDP_IP, pSoap->port, 10);if (soap_valid_socket(sockFD)){printf("%s:%s:%d flag = %d, sockFD = %d, pSoap->master = %d\n", __FILE__, __func__, __LINE__, flag, sockFD, pSoap->master);}else{printf("%s:%s:%d flag = %d\n", __FILE__, __func__, __LINE__, flag);soap_print_fault(pSoap, stderr);}}else{sockFD = soap_bind(pSoap, pIp, pSoap->port, 10);if (soap_valid_socket(sockFD))printf("%s:%s:%d flag = %d, sockFD = %d, pSoap->master = %d\n", __FILE__, __func__, __LINE__, flag, sockFD, pSoap->master);else{printf("%s:%s:%d flag = %d\n", __FILE__, __func__, __LINE__, flag);soap_print_fault(pSoap, stderr);}}return sockFD;
}//加入设备组,设备发现
static void *OnvifBeDiscovered(void *arg) {printf("[%s][%d][%s][%s] start \n", __FILE__, __LINE__, __TIME__, __func__);struct soap UDPserverSoap;struct ip_mreq mcast;soap_init1(&UDPserverSoap, SOAP_IO_UDP | SOAP_XML_IGNORENS);soap_set_namespaces(&UDPserverSoap,  namespaces);int m = soap_bind(&UDPserverSoap, NULL, ONVIF_UDP_PORT, 10);if(!soap_valid_socket(m)){soap_print_fault(&UDPserverSoap, stderr);exit(1);}mcast.imr_multiaddr.s_addr = inet_addr(ONVIF_UDP_IP);mcast.imr_interface.s_addr = htonl(INADDR_ANY);//开启routesystem("route add -net 224.0.0.0 netmask 224.0.0.0 eth0");//IP_ADD_MEMBERSHIP用于加入某个多播组,之后就可以向这个多播组发送数据或者从多播组接收数据if(setsockopt(UDPserverSoap.master, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mcast, sizeof(mcast)) < 0){printf("setsockopt error! error code = %d,err string = %s\n",errno,strerror(errno));return 0;}int fd = -1;while(1){fd = soap_accept(&UDPserverSoap);if (!soap_valid_socket(fd)) {soap_print_fault(&UDPserverSoap, stderr);exit(1);}if( soap_serve(&UDPserverSoap) != SOAP_OK ){soap_print_fault(&UDPserverSoap, stderr);printf("soap_print_fault\n");}soap_destroy(&UDPserverSoap);soap_end(&UDPserverSoap);}//分离运行时的环境soap_done(&UDPserverSoap);pthread_exit(0);
}int main(int argc,char ** argv)
{pthread_t discover = 0;pthread_create(&discover, NULL, OnvifBeDiscovered, NULL);pthread_join(discover, 0);return 0;
}

3. 编译.c文件,生成可执行文件

gcc *.c -o main

生成执行文件之后,直接运行,然后再打开ONVIF Device Manager工具或者ONVIF Device Test Tool工具搜索就成功了。

(注意:服务器和测试工具需要处于同一网段,跨网段的发现需要通过ONVIF代理去实现,这里没有用到代理)

onvif服务器篇之设备发现(onvif discover)相关推荐

  1. onvif 模拟摄像头_ONVIF 设备发现(网络摄像头)——实例笔记

    相关配置 ONVIF官网:http://www.onvif.org/ gSOAP安装配置:gSOAP安装配置+使用案例参考+参考链接 操作系统:CentOS7 资料参考: 许振坪的ONVIF专栏:传送 ...

  2. onvif开发之设备发现功能的实现

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

  3. Onvif备忘录(2)----客户端端设备发现

    续上篇,框架代码生成之后,就可以进行基于Onvif的开发了,先实现一个简单的设备发现的例子. VisualStudio中新建一个空白工程,将上篇中生成的框架代码添加进来,但soapServer.c文件 ...

  4. Onvif之设备发现-基于gsoap2.8.27

    Onvif之设备发现-基于gsoap2.8.27 工具及平台: Gsoap版本:gsoap2.8.27 Onvif :WSDL文档,(2015.12.15最新文档) 框架代码生成:windows下ws ...

  5. ONVIF系列笔记-设备发现机制

    ONVIF系列笔记-设备发现机制 ONVIF系列笔记-功能接口地址的获取 ONVIF系列笔记-流地址的获取 ONVIF系列笔记-PTZ的控制 ONVIF系列笔记-调焦切换及背光控制 SFX流媒体解决方 ...

  6. 开启海康威视摄像头的ONVIF协议,支持onvif设备发现并接入推流器

    海康威视的全系列摄像头都支持onvif协议,但默认都是关闭状态,需要自行手动开启. 在使用迅思维的rtsp转rtmp推流器的时候,需要开启海康威视的onvif协议,这样就能在onvif设备发现里自动获 ...

  7. 03 SkeyeVSS国标视频汇聚云服务使用Onvif协议进行摄像机设备接入以及获取设备信息

    SkeyeVSS国标视频融合云平台基于端-边-云一体化架构,部署轻量简单.功能灵活多样,平台可支持多协议(GB28181/RTSP/Onvif/海康SDK/Ehome/大华SDK/RTMP推流等).多 ...

  8. 思科服务器查看生成树协议,生成树协议、CDP思科设备发现协议、SSH协议

    线路冗余->交换机成环 交换机成环导致: 1 广播风暴 2 mac地址表震荡 一个mac在一台交换机上只能对应一个接口,但一个接口可以对应多个mac 3 重复帧拷贝 生成树协议: 802.1D. ...

  9. 如何发现网络中的设备 设备发现协议(收集)

    如何发现网络中的设备(收集) 如何发现网络中的设备(收集) 好吧,每次要SSH到树莓派都很麻烦,我是没找什么办法,每次都得连上显示器鼠标键盘.才能知道IP地址. 看了点python,写了个脚本来发出 ...

最新文章

  1. 使用Valgrind的callgrind做c/c++代码的code profiling/性能调优
  2. Android开发--RadioButton和CheckBox控件的使用
  3. 2013 Multi-University Training Contest 9 1011 Arc of Dream
  4. 计算机组成SRAM,静态读写存储器(SRAM)-计算机组成原理与汇编语言-电子发烧友网站...
  5. Oracle dataguard 正常切换和应急切换
  6. Emmet语法——HTML和CSS快速生成代码/VS code如何快速格式化代码
  7. 物联网-移远M26模块MQTT开发(AT命令)
  8. luogu_P4767 [IOI2000]邮局
  9. 批量输出lib文件名(PCL或者opencv等环境配置)
  10. Heartbeat+DRBD+NFS 构建高可用的文件系统
  11. Python视觉深度学习系列教程 第三卷 第11章 车辆识别
  12. 联想台式计算机 不启动u盘,联想电脑没有u盘启动项怎么回事_联想电脑bios没有U盘启动项如何处理-系统城...
  13. python办公自动化——批量合并工作簿案例
  14. PDF文件怎么编辑,如何删除其中一页
  15. 会员营销体系中,促成会员转化的关注点有哪些
  16. 免费的播放器软件--mpv
  17. 看穿 137 亿光年,中国天眼会帮我们找到「三体星」吗?|创新大会 2021
  18. 商品下单未支付,如何取消订单?
  19. 【拓展】深度解析蚂蚁Ant Design的设计原则
  20. 麦克表单可以做二维码吗_广告雕刻机可以做浮雕吗?

热门文章

  1. js中字符串和数组互相转换
  2. int(11)是什么意思
  3. 对error C2079: 'stu' uses undefined struct 'Students'的解释
  4. 系统分析员论文12篇合集
  5. 你所说的到底是哪一种
  6. 香农的“创意思维在编程的应用
  7. pycharm import 同路径下.py文件和文件夹报红解决方案
  8. 一键安装5个系统方法,简单易学轻松上手
  9. curl wget 不验证证书进行https请求
  10. 温度芯片(TM75,LM75)