日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2023/12/14 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 onvif 模拟摄像头_ONVIF 设备发现(网络摄像头)——实例笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

相關配置

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 设备发现(网络摄像头)——实例笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。