Linux下onvif服务端之发现设备

本文介绍了一种基于UDP组播实现ONVIF设备发现的方法,重点在于如何正确响应客户端的UUID请求。通过示例代码展示了如何在Linux环境下搭建一个简易的服务端。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于udp组播,没有用gsoap工具,虚拟机伪装成ipc,onvif device test tool作为客户端。

通过wireshark抓包发现,discover的核心是uuid。服务端返回的数据包中必须返回从客户端接收的uuid。

============================================================================

//groupcast_discover_server.c 

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <netdb.h>
//#include <errno.h>
//#include <uuid/uuid.h>

#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="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:SOAP-ENC=\"http://www.w3.org/2003/05/soap-encoding\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:wsdd=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\" xmlns:chan=\"http://schemas.microsoft.com/ws/2005/02/duplex\" xmlns:wsa5=\"http://www.w3.org/2005/08/addressing\" xmlns:xmime=\"http://tempuri.org/xmime.xsd\" xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" xmlns:tt=\"http://www.onvif.org/ver10/schema\" xmlns:wsrfbf=\"http://docs.oasis-open.org/wsrf/bf-2\" xmlns:wstop=\"http://docs.oasis-open.org/wsn/t-1\" xmlns:wsrfr=\"http://docs.oasis-open.org/wsrf/r-2\" xmlns:tdn=\"http://www.onvif.org/ver10/network/wsdl\" xmlns:tds=\"http://www.onvif.org/ver10/device/wsdl\" xmlns:tev=\"http://www.onvif.org/ver10/events/wsdl\" xmlns:wsnt=\"http://docs.oasis-open.org/wsn/b-2\" xmlns:tptz=\"http://www.onvif.org/ver20/ptz/wsdl\" xmlns:trt=\"http://www.onvif.org/ver10/media/wsdl\">\n\
<SOAP-ENV:Header>\n\
<wsa:MessageID>uuid:2419d68a-2dd2-21b2-a205-4A69A95DB56D</wsa:MessageID>\n\
<wsa:RelatesTo>uuid:251984b5-d773-4d2e-a21d-d248cdd2eebf</wsa:RelatesTo>\n\
<wsa:To SOAP-ENV:mustUnderstand=\"true\">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>\n\
<wsa:Action SOAP-ENV:mustUnderstand=\"true\">http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches</wsa:Action>\n\
</SOAP-ENV:Header>\n\
<SOAP-ENV:Body>\n\
<wsdd:ProbeMatches>\n\
<wsdd:ProbeMatch>\n\
<wsa:EndpointReference>\n\
<wsa:Address>urn:uuid:2419d68a-2dd2-21b2-a205-4A69A95DB56D</wsa:Address>\n\
<wsa:ReferenceProperties />\n\
<wsa:ReferenceParameters />\n\
<wsa:PortType>ttl</wsa:PortType>\n\
</wsa:EndpointReference>\n\
<wsdd:Types>tds:Device</wsdd:Types>\n\
<wsdd:Scopes>onvif://www.onvif.org/type/NetworkVideoTransmitter\r\nonvif://www.onvif.org/name/IPC_2802222\r\nonvif://www.onvif.org/location/Country/China</wsdd:Scopes>\n\
<wsdd:XAddrs>http://192.168.42.103:5000/onvif/device_service</wsdd:XAddrs>\n\
<wsdd:MetadataVersion>1</wsdd:MetadataVersion>\n\</wsdd:ProbeMatch>\n\
</wsdd:ProbeMatches>\n\
</SOAP-ENV:Body>\n\
</SOAP-ENV:Envelope>\n\n";
#endif

    char *aa= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:SOAP-ENC=\"http://www.w3.org/2003/05/soap-encoding\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\" xmlns:wsdd=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\" xmlns:chan=\"http://schemas.microsoft.com/ws/2005/02/duplex\" xmlns:wsa5=\"http://www.w3.org/2005/08/addressing\" xmlns:xmime=\"http://tempuri.org/xmime.xsd\" xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" xmlns:tt=\"http://www.onvif.org/ver10/schema\" xmlns:wsrfbf=\"http://docs.oasis-open.org/wsrf/bf-2\" xmlns:wstop=\"http://docs.oasis-open.org/wsn/t-1\" xmlns:wsrfr=\"http://docs.oasis-open.org/wsrf/r-2\" xmlns:tdn=\"http://www.onvif.org/ver10/network/wsdl\" xmlns:tds=\"http://www.onvif.org/ver10/device/wsdl\" xmlns:tev=\"http://www.onvif.org/ver10/events/wsdl\" xmlns:wsnt=\"http://docs.oasis-open.org/wsn/b-2\" xmlns:tptz=\"http://www.onvif.org/ver20/ptz/wsdl\" xmlns:trt=\"http://www.onvif.org/ver10/media/wsdl\">\n\
<SOAP-ENV:Header>\n\
<wsa:MessageID>uuid:2419d68a-2dd2-21b2-a205-4A69A95DB56D</wsa:MessageID>\n\
<wsa:RelatesTo>uuid:";

    char *bb = "</wsa:RelatesTo>\n\
<wsa:To SOAP-ENV:mustUnderstand=\"true\">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>\n\
<wsa:Action SOAP-ENV:mustUnderstand=\"true\">http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches</wsa:Action>\n\
</SOAP-ENV:Header>\n\
<SOAP-ENV:Body>\n\
<wsdd:ProbeMatches>\n\
<wsdd:ProbeMatch>\n\
<wsa:EndpointReference>\n\
<wsa:Address>urn:uuid:2419d68a-2dd2-21b2-a205-4A69A95DB56D</wsa:Address>\n\
<wsa:ReferenceProperties />\n\
<wsa:ReferenceParameters />\n\
<wsa:PortType>ttl</wsa:PortType>\n\
</wsa:EndpointReference>\n\
<wsdd:Types>tds:Device</wsdd:Types>\n\
<wsdd:Scopes>onvif://www.onvif.org/type/NetworkVideoTransmitter\r\nonvif://www.onvif.org/name/IPC_2802222\r\nonvif://www.onvif.org/location/Country/China</wsdd:Scopes>\n\
<wsdd:XAddrs>http://192.168.42.100:5000/onvif/device_service</wsdd:XAddrs>\n\
<wsdd:MetadataVersion>1</wsdd:MetadataVersion>\n\</wsdd:ProbeMatch>\n\
</wsdd:ProbeMatches>\n\
</SOAP-ENV:Body>\n\
</SOAP-ENV:Envelope>\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  groupcast_discover_server.c   -o  groupcast_discover_server

./groupcast_discover_server

Windows下安装运行 "ONVIF Device Test Tool"软件,version 12.12,点击Discover Device:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值