Onvif无法扫描IPC设备的问题解决

一、多网卡选择问题

解决方案:

1.获取本机的各网卡的IP地址

可通过ioctl机制或者getifaddrs方法获取网卡信息

2.在soap中设置网卡的IP地址

组播选项IP_MULTICAST_IF用于设置组播的默认默认网络接口,会从给定的网络接口发送,另一个网络接口会忽略此数据。例如:

struct in_addraddr; 
setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr))
参数addr是希望多播输出接口的IP地址,使用INADDR_ANY地址回送到默认接口。

由于soap内部做了封装,我们只需设置soap的ipv4_multicast_if参数,代码如下:

setScanfIp(soap, "eth0");

void setScanfIp(struct soap *soap, char * name)
{
    int sockfd;
    struct ifreq ifr;

    if(name == NULL)
    {
        DPRINT(ONVIF_ERR, "get ip error, name is NULL\n");
        return;
    }

    strncpy(ifr.ifr_name, name, IFNAMSIZ-1);

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)
    {
        DPRINT(ONVIF_ERR, "create socket error:%s\n", strerror(errno));
        return;
    }
    if(ioctl(sockfd, SIOCGIFADDR, &ifr) == -1)
    {
        DPRINT(ONVIF_ERR, "get scanf ip error:%s\n", strerror(errno));
        close(sockfd);
        return;
    }

    struct sockaddr_in *myaddr;
    myaddr = (struct sockaddr_in*) &(ifr.ifr_addr);
    struct in_addr if_req;
    if_req.s_addr = inet_addr(inet_ntoa(myaddr->sin_addr));  // 想绑定的IP地址  
    soap->ipv4_multicast_if = (char*) soap_malloc(soap, sizeof(struct in_addr));  
    memset(soap->ipv4_multicast_if, 0, sizeof(struct in_addr));  
    memcpy(soap->ipv4_multicast_if, (char*)&if_req, sizeof(if_req));
    close(sockfd);
}
二、 多播组数据的TTL问题

多播选项IP_MULTICAST_TTL允许设置超时TTL,范围为0~255之间的任何值,例如:

unsigned char ttl = 255; 
setsockopt(s,IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

该ttl参数设置数据报最多可以跨过多少个网络,当ttl为0时,指定数据报应停留在本地主机;当ttl的值为1时,指定数据报发送到本地局域网;当ttl的值为32时,意味着只能发送到本站点的网络上;当ttl为64时,意味着数据报应保留在本地区;当ttl的值为128时,意味着数据报应保留在本大洲;当ttl为255时,意味着数据报可发送到所有地方;默认情况下,该ttl的值为1。

解决方案:

我们 只需 设置soap 的ipv4_multicast_ttl参数,代码如下:

soap->ipv4_multicast_ttl = 64;

如果是通过java层的MulticastSocket实现扫描,可调用setTimeToLive(int ttl)方法:

InetAddress inetAddress = InetAddress.getByName("239.255.255.250");
String probeMessage = UtilTools.getProbeMessage();
byte[] buf = probeMessage.getBytes();
mMulticastSocket = new MulticastSocket(port);
mMulticastSocket.setTimeToLive(64);
mMulticastSocket.joinGroup(inetAddress);
DatagramPacket post = new DatagramPacket(buf, buf.length);
post.setPort(3702);
post.setAddress(inetAddress);
mMulticastSocket.send(post);

参考资料:

http://blog.chinaunix.net/uid-28458801-id-5085099.html

http://blog.csdn.net/jiangxinyu/article/details/8158329


你可能感兴趣的:(Onvif无法扫描IPC设备的问题解决)