来自于漂亮的笨蛋的勃客: http://stupidbeauty.com/Blog/2011/04/ 在有2张网卡的机器上udp组播的套接字选项设置/
终于搞出来咯。
要做到的事是勒样的 : 在 1台有2张网卡的机器上,要加入一个组播组 ,并且自己在向组播组发送数据包的时候 ,是以本地的一个指定网卡来发送的。
本座上网查咯好久 ,搞咯好久 ,现在看来终于实现了这个需求 ,只是本座仍然没有确切地搞清楚其中的原理 ,只能凭感觉说一说咯 。
按照本座的感觉 ,在绑定套接字的时候有两个方面的操作:
1. 设置你用来接受这个组播组中的数据包的本地网卡 IP。
2. 设置你用来向这个组播组中发送数据包的本地网卡 IP。
上面的第 1点是用 1个ip_mreq结构体中的.imr_interface . s_addr成员 ( 1个in_addr_t类型的值 ) 来指定的 。第 2点是用一个 setsockopt操作来完成的。分别来说 。
先说第 2点,使用这个操作来指定要使用哪个 IP来发送你的数据包:
setsockopt(cnetsock->sockfd, IPPROTO_IP, IP_MULTICAST_IF, InterfaceAddr, sizeof ( *InterfaceAddr))
其中的 InterfaceAddr是一个 ( in_addr_t * ),它表示的是一个 IP地址。例如你要使用本地的 “192.168.0.202”这个IP对应的网卡来发送你的数据包,则使用 “inet_addr()”函数将“192.168.0.202”转换成 in_addr_t来赋值给InterfaceAddr指向的内存 ,再用上面的 setsockopt操作设置一下就行咯 。
再说第 1点,首先 ,要加入一个组播组的话,需要使用另一个setsockopt操作:
setsockopt(cnetsock->sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof ( struct ip_mreq))
其中的 mreq是一个ip_mreq类型的变量 。通过指定它的 ip_mreq.imr_interface.s_addr成员就能设置要在本地的哪个 IP对应的网卡上监听这个组播组的数据包。
本来本座在这里是将它设置成与第 2点中要用来发送的IP相同的,也就是“192.168.0.202”,但是测试发现竟然没有再收到来自于组播组的数据包咯 。本座难过咯半天,最后将它设置成INADDR_ANY,竟然收到咯。对这一点 ,本座想到的解释就是,另一个网卡 192.168.0.201是系统的默认网卡,组播组的数据包可能是被内核转到那个网卡咯 ,而本座监听的是 192.168.0.202,所以就没收到咯。对不对 ,就看砖家的解释及后来人的实验 咯。
在加入组播组时 ,你用来发送数据包的网卡跟你用来接收数据包的网卡是两回事 ,如果不希望内核随机为你挑选网卡来发送数据包的话 , 应当将用来发送的网卡设置成指定的单个网卡 ,而将用来接收的网卡设置成 “任意网卡” ,这样,既能控制自己向外发送的出口又不會漏掉组中其它成员发给你的数据包咯。
至于其它的代码 ,按照网路上搜到的来写即可咯。
HxLauncher: Launch Android applications by voice commands