需要适用于iOS 9的IPv6组播C代码

前端之家收集整理的这篇文章主要介绍了需要适用于iOS 9的IPv6组播C代码前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
苹果现在要求iOS 9应用符合IPv6.我们几乎可以,除了一些发送UDP广播的代码 – 现在在iOS 9中失败了.

我看到的一切告诉我,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上多播“有人在吗?”):

  1. char *msg = "Is anybody out there?";
  2. err = multicast_udp_msg ( "FF01::1111",4031,msg,strlen(msg) );

这是正在调用代码

  1. // Multicasts a message on a specific UDP port.
  2. // myhost - IPv6 address on which to multicast the message (i.e.,ourself)
  3. // port - UDP port on which to broadcast the mssage
  4. // msg - message contents to broadcast
  5. // msgsize - length of message in bytes
  6. // Return value is zero if successful,or nonzero on error.
  7.  
  8. int multicast_udp_msg ( char *myhost,short port,char *msg,size_t msgsize )
  9. {
  10. int sockfd,n;
  11. char service[16] = { 0 };
  12. int err = 0;
  13. struct addrinfo hints = { 0 },*res,*ressave;
  14. struct sockaddr_storage addr = { 0 };
  15.  
  16. hints.ai_family = AF_INET6;
  17. hints.ai_socktype = SOCK_DGRAM;
  18.  
  19. sprintf ( service,"%hd",port );
  20. n = getaddrinfo ( myhost,service,&hints,&res );
  21. if ( n < 0 )
  22. {
  23. fprintf(stderr,"getaddrinfo error:: [%s]\n",gai_strerror(n));
  24. return -1;
  25. }
  26.  
  27. ressave = res;
  28.  
  29. sockfd = socket ( res->ai_family,res->ai_socktype,res->ai_protocol );
  30. if ( sockfd >= 0 )
  31. {
  32. memcpy ( &addr,res->ai_addr,sizeof ( addr ) );
  33. if ( joinGroup ( sockfd,8,&addr ) == 0 )
  34. if ( bind ( sockfd,res->ai_addrlen ) == 0 )
  35. if ( sendto ( sockfd,msgsize,(struct sockaddr *) &addr,sizeof ( addr ) ) < 0 )
  36. err = errno;
  37.  
  38. close ( sockfd );
  39.  
  40. res = res->ai_next;
  41. }
  42.  
  43. freeaddrinfo ( ressave );
  44. return err;
  45. }
  46.  
  47. int
  48. joinGroup(int sockfd,int loopBack,int mcastTTL,struct sockaddr_storage *addr)
  49. {
  50. int r1,r2,r3,retval;
  51.  
  52. retval=-1;
  53.  
  54. switch (addr->ss_family) {
  55. case AF_INET: {
  56. struct ip_mreq mreq;
  57.  
  58. mreq.imr_multiaddr.s_addr=
  59. ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  60. mreq.imr_interface.s_addr= INADDR_ANY;
  61.  
  62. r1= setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_LOOP,&loopBack,sizeof(loopBack));
  63. if (r1<0)
  64. perror("joinGroup:: IP_MULTICAST_LOOP:: ");
  65.  
  66. r2= setsockopt(sockfd,IP_MULTICAST_TTL,&mcastTTL,sizeof(mcastTTL));
  67. if (r2<0)
  68. perror("joinGroup:: IP_MULTICAST_TTL:: ");
  69.  
  70. r3= setsockopt(sockfd,IP_ADD_MEMBERSHIP,(const void *)&mreq,sizeof(mreq));
  71. if (r3<0)
  72. perror("joinGroup:: IP_ADD_MEMBERSHIP:: ");
  73.  
  74. } break;
  75.  
  76. case AF_INET6: {
  77. struct ipv6_mreq mreq6;
  78.  
  79. memcpy(&mreq6.ipv6mr_multiaddr,&(((struct sockaddr_in6 *)addr)->sin6_addr),sizeof(struct in6_addr));
  80.  
  81. mreq6.ipv6mr_interface= 0; // cualquier interfaz
  82.  
  83. r1= setsockopt(sockfd,IPPROTO_IPV6,IPV6_MULTICAST_LOOP,sizeof(loopBack));
  84. if (r1<0)
  85. perror("joinGroup:: IPV6_MULTICAST_LOOP:: ");
  86.  
  87. r2= setsockopt(sockfd,IPV6_MULTICAST_HOPS,sizeof(mcastTTL));
  88. if (r2<0)
  89. perror("joinGroup:: IPV6_MULTICAST_HOPS:: ");
  90.  
  91. r3= setsockopt(sockfd,IPV6_JOIN_GROUP,&mreq6,sizeof(mreq6));
  92. if (r3<0)
  93. perror("joinGroup:: IPV6_ADD_MEMBERSHIP:: ");
  94.  
  95. } break;
  96.  
  97. default:
  98. r1=r2=r3=-1;
  99. }
  100.  
  101. if ((r1>=0) && (r2>=0) && (r3>=0))
  102. retval=0;
  103.  
  104. return retval;
  105. }

想念欢迎!

-Tim

解决方法

在与苹果一起来之后,还有一些额外的环境,我们有一个答案.但这不是我原来问题的答案.首先,这里是Apple线程的上下文:

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问题)时,苹果也给我们带来了失败的可能原因.

所以,虽然我原来的问题在这里没有回答,但是基本问题已经解决了.

猜你在找的iOS相关文章