一、多网卡选择问题
解决方案:
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 = 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