我看到的一切告诉我,UDP组播是在IPv6中这样做的正确方法.我已经找到一些示例代码,但是在我尝试过的任何版本的iOS或Mac OS X上都无效.
这个代码是从我们程序中的C/C++ lib调用的 – 很难回调到Swift,Obj-C,Java等.这段代码将由我们的应用程序的Mac OS X和Android版本共享.有人会认为可以在任何POSIX环境中的C中进行IPv6组播!
在下面的示例中,执行成功到最终的sendto()调用,实际发送UDP消息.失败后sendto()失败,errno设置为EbroKENPIPE(22).
我最好的猜测是我缺少一些需要的setsockopt()调用,或者使用错误的多播地址.现在,我被困了
这是我正在做的函数调用(在UDP端口4031上多播“有人在吗?”):
char *msg = "Is anybody out there?"; err = multicast_udp_msg ( "FF01::1111",4031,msg,strlen(msg) );
// Multicasts a message on a specific UDP port. // myhost - IPv6 address on which to multicast the message (i.e.,ourself) // port - UDP port on which to broadcast the mssage // msg - message contents to broadcast // msgsize - length of message in bytes // Return value is zero if successful,or nonzero on error. int multicast_udp_msg ( char *myhost,short port,char *msg,size_t msgsize ) { int sockfd,n; char service[16] = { 0 }; int err = 0; struct addrinfo hints = { 0 },*res,*ressave; struct sockaddr_storage addr = { 0 }; hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; sprintf ( service,"%hd",port ); n = getaddrinfo ( myhost,service,&hints,&res ); if ( n < 0 ) { fprintf(stderr,"getaddrinfo error:: [%s]\n",gai_strerror(n)); return -1; } ressave = res; sockfd = socket ( res->ai_family,res->ai_socktype,res->ai_protocol ); if ( sockfd >= 0 ) { memcpy ( &addr,res->ai_addr,sizeof ( addr ) ); if ( joinGroup ( sockfd,8,&addr ) == 0 ) if ( bind ( sockfd,res->ai_addrlen ) == 0 ) if ( sendto ( sockfd,msgsize,(struct sockaddr *) &addr,sizeof ( addr ) ) < 0 ) err = errno; close ( sockfd ); res = res->ai_next; } freeaddrinfo ( ressave ); return err; } int joinGroup(int sockfd,int loopBack,int mcastTTL,struct sockaddr_storage *addr) { int r1,r2,r3,retval; retval=-1; switch (addr->ss_family) { case AF_INET: { struct ip_mreq mreq; mreq.imr_multiaddr.s_addr= ((struct sockaddr_in *)addr)->sin_addr.s_addr; mreq.imr_interface.s_addr= INADDR_ANY; r1= setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_LOOP,&loopBack,sizeof(loopBack)); if (r1<0) perror("joinGroup:: IP_MULTICAST_LOOP:: "); r2= setsockopt(sockfd,IP_MULTICAST_TTL,&mcastTTL,sizeof(mcastTTL)); if (r2<0) perror("joinGroup:: IP_MULTICAST_TTL:: "); r3= setsockopt(sockfd,IP_ADD_MEMBERSHIP,(const void *)&mreq,sizeof(mreq)); if (r3<0) perror("joinGroup:: IP_ADD_MEMBERSHIP:: "); } break; case AF_INET6: { struct ipv6_mreq mreq6; memcpy(&mreq6.ipv6mr_multiaddr,&(((struct sockaddr_in6 *)addr)->sin6_addr),sizeof(struct in6_addr)); mreq6.ipv6mr_interface= 0; // cualquier interfaz r1= setsockopt(sockfd,IPPROTO_IPV6,IPV6_MULTICAST_LOOP,sizeof(loopBack)); if (r1<0) perror("joinGroup:: IPV6_MULTICAST_LOOP:: "); r2= setsockopt(sockfd,IPV6_MULTICAST_HOPS,sizeof(mcastTTL)); if (r2<0) perror("joinGroup:: IPV6_MULTICAST_HOPS:: "); r3= setsockopt(sockfd,IPV6_JOIN_GROUP,&mreq6,sizeof(mreq6)); if (r3<0) perror("joinGroup:: IPV6_ADD_MEMBERSHIP:: "); } break; default: r1=r2=r3=-1; } if ((r1>=0) && (r2>=0) && (r3>=0)) retval=0; return retval; }
想念欢迎!
-Tim
解决方法
https://forums.developer.apple.com/message/71107
事实证明,IPv6组播实际上并不是我们需要解决现有的问题 – 即在本地Wi-Fi网络上找到一个传统的嵌入式设备.我们真的不得不使用IPv4 UDP广播来做到这一点.我们的嵌入式设备忽略IPv6组播数据包,如地球忽略中微子飞过它.
苹果给了我们一个setsockopt()调用,它使IPv4 UDP广播能够在基础设施Wi-Fi网络上的iOS 9中运行.这是该功能的预期用例.而当广播无法在Ad Hoc Wi-Fi网络中工作(这似乎是已知的iOS 9问题)时,苹果也给我们带来了失败的可能原因.
原文地址:https://www.jb51.cc/iOS/329287.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。