相关配置

ONVIF官网:http://www.onvif.org/

gSOAP安装配置:gSOAP安装配置+使用案例参考+参考链接

操作系统:CentOS7

资料参考:

许振坪的ONVIF专栏:传送门

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

Linux下onvif服务端之发现设备

还有一个博文找不到网址了,如果网友发现可以私信补充。

代码实战

完整源码下载:GitHub,码云

客户端

1、WS-Discovery的Ad hoc模式,使用多播(不使用gSOAP实现设备发现)

参考文章:ONVIF协议网络摄像机(IPC)客户端程序开发(7):设备搜索

源码如下 search_c.c:

#include

#include

#include

#ifdef WIN32

#include

#else

#include

#include

#include

#include

#include

#endif

/* 从技术层面来说,通过单播、多播、广播三种方式都能探测到IPC,但多播最具实用性*/

#define COMM_TYPE_UNICAST 1// 单播

#define COMM_TYPE_MULTICAST 2// 多播

#define COMM_TYPE_BROADCAST 3// 广播

#define COMM_TYPE COMM_TYPE_MULTICAST

/* 发送探测消息(Probe)的目标地址、端口号 */

#if COMM_TYPE == COMM_TYPE_UNICAST

#define CAST_ADDR "100.100.100.15"// 单播地址,预先知道的IPC地址

#elif COMM_TYPE == COMM_TYPE_MULTICAST

#define CAST_ADDR "239.255.255.250"// 多播地址,固定的239.255.255.250

#elif COMM_TYPE == COMM_TYPE_BROADCAST

#define CAST_ADDR "100.100.100.255"// 广播地址

#endif

#define CAST_PORT 3702// 端口号

/* 以下几个宏是为了socket编程能够跨平台,这几个宏是从gsoap中拷贝来的 */

#ifndef SOAP_SOCKET

# ifdef WIN32

# define SOAP_SOCKET SOCKET

# define soap_closesocket(n) closesocket(n)

# else

# define SOAP_SOCKET int

# define soap_closesocket(n) close(n)

# endif

#endif

#if defined(_AIX) || defined(AIX)

# if defined(_AIX43)

# define SOAP_SOCKLEN_T socklen_t

# else

# define SOAP_SOCKLEN_T int

# endif

#elif defined(SOCKLEN_T)

# define SOAP_SOCKLEN_T SOCKLEN_T

#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(OPENBSD) || defined(__QNX__) || defined(QNX) || defined(OS390) || defined(__ANDROID__) || defined(_XOPEN_SOURCE)

# define SOAP_SOCKLEN_T socklen_t

#elif defined(IRIX) || defined(WIN32) || defined(__APPLE__) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) || defined(HP_UX)

# define SOAP_SOCKLEN_T int

#elif !defined(SOAP_SOCKLEN_T)

# define SOAP_SOCKLEN_T size_t

#endif

#ifdef WIN32

#define SLEEP(n) Sleep(1000 * (n))

#else

#define SLEEP(n) sleep((n))

#endif

/* 探测消息(Probe),这些内容是ONVIF Device Test Tool 15.06工具搜索IPC时的Probe消息,通过Wireshark抓包工具抓包到的 */

const char *probe = "uuid:fc0bad56-5f5a-47f3-8ae2-c94a4e907d70urn:schemas-xmlsoap-org:ws:2005:04:discoveryhttp://schemas.xmlsoap.org/ws/2005/04/discovery/Probedn:NetworkVideoTransmitter";

int main(int argc, char **argv)

{

int ret;

int optval;

SOAP_SOCKET s;

SOAP_SOCKLEN_T len;

char recv_buff[4096] = {0};

struct sockaddr_in multi_addr;

struct sockaddr_in client_addr;

#ifdef WIN32

WSADATA wsaData;

if( WSAStartup(MAKEWORD(2,2), &wsaData) != 0 ) { // 初始化Windows Sockets DLL

printf("Could not open Windows connection.\n");

return 0;

}

if ( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 ) {

printf("the version of WinSock DLL is not 2.2.\n");

return 0;

}

#endif

s = socket(AF_INET, SOCK_DGRAM, 0); // 建立数据报套接字

if (s < 0) {

perror("socket error");

return -1;

}

#if COMM_TYPE == COMM_TYPE_BROADCAST

optval = 1;

ret = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (const char*)&optval, sizeof(int));

#endif

multi_addr.sin_family = AF_INET; // 搜索IPC:使用UDP向指定地址发送探测消息(Probe)

multi_addr.sin_port = htons(CAST_PORT);

multi_addr.sin_addr.s_addr = inet_addr(CAST_ADDR);

ret = sendto(s, probe, strlen(probe), 0, (struct sockaddr*)&multi_addr, sizeof(multi_addr));

if (ret < 0) {

soap_closesocket(s);

perror("sendto error");

return -1;

}

printf("Send Probe message to [%s:%d]\n\n", CAST_ADDR, CAST_PORT);

SLEEP(1);

for (;;) { // 接收IPC的应答消息(ProbeMatch)

len = sizeof(client_addr);

memset(recv_buff, 0, sizeof(recv_buff));

memset(&client_addr, 0, sizeof(struct sockaddr));

ret = recvfrom(s, recv_buff, sizeof(recv_buff) - 1, 0, (struct sockaddr*)&client_addr, &len);

printf("===Recv ProbeMatch from [%s:%d]===\n%s\n\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), recv_buff);

SLEEP(1);

}

soap_closesocket(s);

return 0;

}

Linux编译: gcc search_c.c , Windows下编译: gcc search_c.c -lws2_32

Windows下效果和Linux下效果一样。

我Linux是用的虚拟机,所以需要关闭防火墙,不然搜不到 systemctl stop iptables.service 或 service iptables stop

我们也使用 ONVIF Device Test Tool,测一下

2、使用gSOAP生成ONVIF框架,编写客户端

如何生成ONVIF框架参考:ONVIF协议网络摄像机(IPC)客户端程序开发(6):使用gSOAP生成ONVIF框架代码,原文没有生成soapServer.c,我在评论里面写了如何修改,可以参考。

部分文件下载于:GitHub

参考文章:onvif开发之设备发现功能的实现

我做的相关改动都写在评论区了,server编译通不过,但client是可行的。

client.c源码如下:

#include

#include

#include

#include "soapH.h"

#include "soapStub.h"

#include "wsdd.nsmap"

#include "wsaapi.h"

#define MULTICAST_ADDRESS "soap.udp://239.255.255.250:3702"

int main()

{

printf("[%s][%d][%s][%s] start \n", __FILE__, __LINE__, __TIME__, __func__);

int result = 0;

wsdd__ProbeType req;

struct __wsdd__ProbeMatches resp;

wsdd__ScopesType sScope;

struct SOAP_ENV__Header header;

struct soap *soap;

soap = soap_new();

if(NULL == soap )

{

printf("sopa new error\r\n");

return -1;

}

soap->recv_timeout = 10;

soap_set_namespaces(soap, namespaces);

soap_default_SOAP_ENV__Header(soap, &header);

uuid_t uuid;

char guid_string[100];

uuid_generate(uuid);

uuid_unparse(uuid, guid_string);

header.wsa__MessageID = guid_string;

header.wsa__To = "urn:schemas-xmlsoap-org:ws:2005:04:discovery";

header.wsa__Action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";

soap->header = &header;

soap_default_wsdd__ScopesType(soap, &sScope);

sScope.__item = "";

soap_default_wsdd__ProbeType(soap, &req);

req.Scopes = &sScope;

req.Types = "dn:NetworkVideoTransmitter";

//"dn:NetworkVideoTransmitter";

int i = 0;

result = soap_send___wsdd__Probe(soap, MULTICAST_ADDRESS, NULL, &req);

while(result == SOAP_OK)

{

result = soap_recv___wsdd__ProbeMatches(soap, &resp);

if(result == SOAP_OK)

{

if(soap->error)

{

printf("soap error 1: %d, %s, %s\n", soap->error, *soap_faultcode(soap), *soap_faultstring(soap));

result = soap->error;

}

else

{

printf("guog *********************************************\r\n");

if(soap->header->wsa__MessageID)

{

printf("MessageID : %s\r\n", soap->header->wsa__MessageID);

}

if(soap->header->wsa__RelatesTo && soap->header->wsa__RelatesTo->__item)

{

printf("RelatesTo : %s\r\n", soap->header->wsa__RelatesTo->__item);

}

if(soap->header->wsa__To)

{

printf("To : %s\r\n", soap->header->wsa__To);

}

if(soap->header->wsa__Action)

{

printf("Action : %s\r\n", soap->header->wsa__Action);

}

for(i = 0; i < resp.wsdd__ProbeMatches->__sizeProbeMatch; i++)

{

printf("__sizeProbeMatch : %d\r\n", resp.wsdd__ProbeMatches->__sizeProbeMatch);

printf("wsa__EndpointReference : %p\r\n", resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference);

printf("Target EP Address : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address);

printf("Target Type : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->Types);

printf("Target Service Address : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->XAddrs);

printf("Target Metadata Version : %d\r\n", resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion);

if(resp.wsdd__ProbeMatches->ProbeMatch->Scopes)

{

printf("Target Scopes Address : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->Scopes->__item);

}

}

}

}

else if (soap->error)

{

printf("[%d] soap error 2: %d, %s, %s\n", __LINE__, soap->error, *soap_faultcode(soap), *soap_faultstring(soap));

result = soap->error;

}

}

soap_destroy(soap);

soap_end(soap);

soap_free(soap);

printf("[%d] guog discover over !\n", __LINE__);

return result;

}

Linux下编译: gcc -o client client.c stdsoap2.c soapC.c soapClient.c wsaapi.c duration.c -luuid

没有libuuid库,可自行安装,命令仅供参考 sudo apt-get install uuid-dev

效果如图:

服务端

1、不使用gSOAP,虚拟机伪装成ipc

文章参考:Linux下onvif服务端之发现设备

代码如下 ipc_server_c.c:

#include

#include

#include

#include

#include

#include

//#include

//#include

//#include

#define BUFLEN 4095

int main (int argc, char **argv)

{

char uu_buf[1024]={0};

char *cust_uuid = 0;

struct sockaddr_in groupcast_addr,the_member;

int sockfd;

unsigned char loop;

char recmsg[BUFLEN + 1];

unsigned int socklen, n;

struct ip_mreq mreq;

#if 0

char *msg="\n\

\n\

\n\

uuid:2419d68a-2dd2-21b2-a205-4A69A95DB56D\n\

uuid:251984b5-d773-4d2e-a21d-d248cdd2eebf\n\

http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous\n\

http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches\n\\n\

\n\

\n\

\n\

\n\

urn:uuid:2419d68a-2dd2-21b2-a205-4A69A95DB56D\n\

\n\

\n\

ttl\n\\n\

tds:Device\n\

onvif://www.onvif.org/type/NetworkVideoTransmitter\r\nonvif://www.onvif.org/name/IPC_2802222\r\nonvif://www.onvif.org/location/Country/China\n\

http://192.168.42.103:5000/onvif/device_service\n\

1\n\\n\\n\

\n\\n\n";

#endif

char *aa= "\n\

\n\

\n\

uuid:2419d68a-2dd2-21b2-a205-4A69A95DB56D\n\

uuid:";

char *bb = "\n\

http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous\n\

http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches\n\

\n\

\n\

\n\

\n\

\n\

urn:uuid:2419d68a-2dd2-21b2-a205-4A69A95DB56D\n\

\n\

\n\

ttl\n\\n\

tds:Device\n\

onvif://www.onvif.org/type/NetworkVideoTransmitter\r\nonvif://www.onvif.org/name/IPC_2802222\r\nonvif://www.onvif.org/location/Country/China\n\

http://192.168.42.100:5000/onvif/device_service\n\

1\n\\n\\n\

\n\

\n\n";

/* 创建 socket 用于UDP通讯 */

sockfd = socket (AF_INET, SOCK_DGRAM, 0);

if (sockfd < 0)

{

printf ("socket creating err in udptalk\n");

exit (1);

}

/* 设置要加入组播的地址 */

bzero(&mreq, sizeof (struct ip_mreq));

inet_pton(AF_INET,"239.255.255.250",&the_member.sin_addr);

/* 设置组地址 */

bcopy (&the_member.sin_addr.s_addr, &mreq.imr_multiaddr.s_addr, sizeof (struct in_addr));

/* 设置发送组播消息的源主机的地址信息 */

mreq.imr_interface.s_addr = htonl (INADDR_ANY);

/* 把本机加入组播地址,即本机网卡作为组播成员,只有加入组才能收到组播消息 */

//if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP | IP_MULTICAST_LOOP, &mreq,sizeof (struct ip_mreq)) == -1)

if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP , &mreq,sizeof (struct ip_mreq)) == -1)

{

perror ("setsockopt");

exit (-1);

}

loop = 0;

if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,sizeof (loop)) == -1)

{

printf("IP_MULTICAST_LOOP set fail!\n");

}

socklen = sizeof (struct sockaddr_in);

memset (&groupcast_addr, 0, socklen);

groupcast_addr.sin_family = AF_INET;

groupcast_addr.sin_port = htons (3702);

inet_pton(AF_INET, "239.255.255.250", &groupcast_addr.sin_addr);

/* 绑定自己的端口和IP信息到socket上 */

if (bind(sockfd, (struct sockaddr *) &groupcast_addr,sizeof (struct sockaddr_in)) == -1)

{

printf ("Bind error\n");

exit (0);

}

while (1)

{

bzero (recmsg, BUFLEN + 1);

n = recvfrom (sockfd, recmsg, BUFLEN, 0, (struct sockaddr *) &the_member, &socklen);

if (n < 0)

{

printf ("recvfrom err in udptalk!\n");

exit (4);

}

else{

recmsg[n] = 0;

printf ("recv:[%s]\n\n", recmsg);

printf("ip:%s\n",inet_ntoa(the_member.sin_addr));

printf("port:%d\n", ntohs(the_member.sin_port));

}

cust_uuid = strstr(recmsg, "uuid:"); //获取recmsg字符串中 子字符串"uuid:"的位置

if (cust_uuid == 0)

{

printf("uuid: err!\n");

return 0;

}

cust_uuid += 5; //获取接收的uuid的值

strncpy(uu_buf, cust_uuid, 36);

printf("%s\n",uu_buf);

memset(recmsg,0,sizeof(recmsg));

strcpy(recmsg, aa);

strcat(recmsg, uu_buf);

strcat(recmsg, bb);

if (sendto(sockfd, recmsg, strlen (recmsg), 0, (struct sockaddr *) &the_member, sizeof (the_member)) < 0)

{

printf ("sendto error!\n");

exit (3);

}

printf ("send ok\n");

break;

}

}

Linux下编译:gcc ipc_server_c.c -o ipc_server

直接运行

现在我们用 ONVIF Device Test Tool,测试一下

ONVIF Device Test Tool 搜索后,服务端就打印了这些信息

ifconfig查看下虚拟机ip地址

同样可以被我们之前写的 客户端 搜索到

2、使用gSOAP生成ONVIF框架,编写服务端

文件下载于:GitHub

参考文章:onvif服务器篇之onvif 服务器框架的搭建

碰到的问题同样写在评论区,可自行查看。

修改Makefile,GSOAP_ROOT改成自己的soap路径

终端 make 编译。生成 deviceserver

我们直接运行 ./deviceserver

我们同样用 ONVIF Device Test Tool,搜索一下

服务端也有所反应

那么本次的服务端和客户端都测试完毕了。网上资料不多,真的进行的十分困难。

相关链接

ONVIF官网:http://www.onvif.org/

gSOAP安装配置:gSOAP安装配置+使用案例参考+参考链接

许振坪的ONVIF专栏

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

Linux下onvif服务端之发现设备

ONVIF协议网络摄像机(IPC)客户端程序开发(7):设备搜索

ONVIF协议网络摄像机(IPC)客户端程序开发(6):使用gSOAP生成ONVIF框架代码

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

Linux下onvif服务端之发现设备

GitHub服务端下载

onvif服务器篇之onvif 服务器框架的搭建

ONVIF Device Test Tool

onvif 模拟摄像头_ONVIF 设备发现(网络摄像头)——实例笔记相关推荐

  1. python网络摄像头模拟usb摄像头_Python27+Opencv3 捕获网络摄像头IPCamera实时视频

    Opencv3+Python比较常见的是播放本地avi视频文件.或者捕获PC自带摄像头视频. 现在网络摄像机遍布,而我们测试时也需要用到网络摄像机的实时视频,并进行处理,参考<opencv3计算 ...

  2. python 网络摄像头安装图解_网络摄像头在opencv-python和opencv-contrib-python...

    我一直在使用anaconda在python中的opencv中遇到网络摄像头问题. 问题如下: 如果通过以下两种方式之一安装了opencv,则无法打开网络摄像头: pip install opencv- ...

  3. onvif服务器篇之设备发现(onvif discover)

    一.设备发现的机制 从ONVIF的官方文档中可以了解到,客户端在UDP协议下,向网段内的组播地址239.255.255.250,端口3702,不断地向四周发送Probe消息探针,而网段内的服务器在接收 ...

  4. 网络摄像头python_Python OpenCV 调用网络摄像头

    OpenCV调用摄像头 环境 python:python3.6 摄像头:网络摄像头 Python库:openCV # -*- coding: utf-8 -*- # @author leone # @ ...

  5. (202103更新)海康威视网络摄像头sdk python版 (报错排查) 移动物体检测 多通道海康威视网洛摄像头后台检测 海康威视网络摄像头Python SDK

    海康威视网络摄像头Python SDK+移动物体位置检测 文末附 海康威视网络摄像头Python SDK 下载链接 本文参考博客 https://blog.csdn.net/c20081052/art ...

  6. 海康网络摄像头android,海康网络摄像头的Android端Demo

    [实例简介]海康网络摄像头的Android端Demo; 可实现通过wifi实时读取并显示摄像头捕捉的画面; [实例截图] [核心代码] /** * DemoActivity Class * @auth ...

  7. linux搭建网络摄像头,用树莓派搭建网络摄像头

    备份自:http://blog.rainy.im/2015/05/26/webcam-on-raspberry-pi/ 用树莓派加上相机模块,可以实现实时监控的功能,再将时时视频流导入到 Web 界面 ...

  8. Linux网络摄像头设备端调试过程

    转载请标明出处:https://blog.csdn.net/u013752202/article/details/96502576 简介 网络摄像头,即常说的免驱摄像头,其采用UVC协议通过USB跟主 ...

  9. 测试:将手机摄像头用作网络摄像头的拍摄效果

    我在手机上测试了一些虚拟网络摄像头软件. 作者 / Chris Kranky 原文链接 / https://www.chriskranky.com/using-your-mobile-camera-a ...

最新文章

  1. arduino并口屏_Arduino 驱动串口屏(入门级)
  2. 安装jdk配置环境、cmd命令行测试环境变量配置是否正确及运行java程序、安装IDEA编写代码测试
  3. php数组删除重复的,从PHP中的数组中删除重复的元素
  4. oracle 12c dg新特性,Oracle 12c DG新特性---一键switchover
  5. Android 防火墙 知乎,知乎回应:防火墙太“坑爹” 正检查用户隐私是否有泄露...
  6. 最佳实践:使用负载均衡SLB IPv6搞定苹果AppStore审核
  7. html5 retina 1像素,走向视网膜(Retina)的Web时代
  8. 零基础怎么玩转可视化大屏?这个工具只需5步!
  9. Office LTSC 2021 for Mac
  10. 2019电子设计大赛:纸张计数显示装置
  11. Oracle EBS 寄销/VMI(1)--基础设置
  12. The remote end hung up unexpectedly The remote end hung up unexpectedly RPC failed;
  13. pandas过滤某列含有nan 的行
  14. 分水岭算法java,C++实现分水岭算法(Watershed Algorithm)
  15. Vue的安装及使用教程【超详细图文教程】
  16. 批量修改文件夹下文件的名字
  17. 南阳理工学院计算机应用基础答案,南阳理工学院国家省校级精品课程(精品资源共享课程)一览表.doc...
  18. linux如何查看disk状态类型,Linux下如何查看你的disk的信息
  19. 如何在windows电脑上完成原神签到、祈愿抽卡分析等功能
  20. 2020 GDUT Rating Contest III (Div2)

热门文章

  1. 题目 - 北京地铁 描述 北京地铁涨价了,现在的地铁票价计算方法如下: 6公里内 3元 (包括6公里) 6-12 公里 4元 (不包括6公里,包括12公里) 12-32 公里 每10公里加1元
  2. 【人工智能项目】深度学习实现汉字书法识别
  3. ZT自老罗的博客 Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析...
  4. 架构师小跟班:推荐一款Java在线诊断工具,arthas入门及使用教程
  5. webpack 报错Cannot find module 'opn'
  6. 《从零开始的记账本开发》第1篇 需求分析
  7. 云原生安全,这也是一道必答题
  8. 以太坊环境以及Solidity学习笔记
  9. Java练习题__删除公共字符
  10. 计算机科学与技术职业生涯规划,计算机科学与技术职业生涯规划ppt