Linux下onvif服务端之发现设备

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

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

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

//groupcast_discover_server.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  groupcast_discover_server.c   -o  groupcast_discover_server

./groupcast_discover_server

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

Linux下onvif服务端之发现设备_第1张图片

你可能感兴趣的:(onvif协议开发)