战魂小筑

讨论群:309800774 知乎关注:http://zhihu.com/people/sunicdavy 开源项目:https://github.com/davyxu

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  257 随笔 :: 0 文章 :: 506 评论 :: 0 Trackbacks

苹果要求在2016年6月1日后新的app必须支持ipv6网络, 技术发展靠苹果果然没错, 但开发者还是要开始忙起来了
这里介绍下Unity3D的适配的一些经验

基本注意点

  • ios ipv6适配无需修改服务器, 也就是说, 如果你的服务器依然是ipv4的也是可以使用的
  • 苹果的适配方案是将ipv4的地址转换为ipv6, 到了路由层再转回去继续利用ipv4网络传输

测试网络环境搭建

转载请注明:http://www.cppblog.com/sunicdavy战魂小筑

网上有很多翻译了苹果官方的搭建ipv6测试网络环境的文章, 例如:
http://www.cocoachina.com/ios/20160525/16431.html
注意以下几点

  • 无需路由器支持ipv6, 但猫(modem)必须要支持ipv6. 因为现在大多数都是光猫
    以下截图是光猫管理端
    3440e3f9-12de-435b-85ab-a7a3be8b384b[6]
    光猫里的ipv6支持默认是关闭的, 所以需要手动打开, 按默认值配置即可

  • 请确认mac os系统必须是osx 10.11以后的版本才可以打开NAT64

  • 正确连接mac的ios设备应是如下截图示意
    91f54476-4b5d-4585-a364-0da2139774c1[6]

  • 默认连接上wifi时看连接信息时, 一般只会有红色DNS地址或者根本不显示
  • 只有在第一次访问网络, 例如打开浏览器进入任意网站时, 才会显示上面的几条信息
  • 如果只有DNS没有IP地址和子网掩码, 一般是光猫没有打开ipv6的DHCP, 没有分配IP
  • 还有一种测试ipv6 DHCP是否正常工作的方法: 关闭NAT64时可以上网, 但打开NAT64无法上网

转载请注明:http://www.cppblog.com/sunicdavy战魂小筑

Unity3D的Socket适配

WWW类本身已经支持了IPV6, 无需处理, 这里讲解使用C#原生Socket的处理

  • 测试用的设备的iOS版本必须是9.3以上的
  • Socket构造时, AddressFamily 设置为InterNetworkV6时只支持ipv6网络, 传入InterNetwork时只支持ipv4网络
  • 4.7.2和5.4.3的当前版本在mono层并未支持ipv6代码适配的核心函数getaddrinfo, 因此需要通过oc层做转换, 以下是代码
    这段代码将getaddrinfo的地址转换成一个完整字符串, 格式是:
    ipv4|ipv4地址|ipv6|ipv6地址|

P.S. copyStr这种用法参考了http://www.codeinsect.net/blog/2016/05/26/unity-ipv6-socket-%E6%94%AF%E6%8C%81%EF%BC%8C%E5%B7%B2%E6%B5%8B%E8%AF%95%E9%80%9A%E8%BF%87/
会造成内存泄露, 如果有更好的方法欢迎反馈

转载请注明:http://www.cppblog.com/sunicdavy战魂小筑

iosaddrinfo.mm

   1:  #include <sys/socket.h>
   2:  #include <netdb.h>
   3:  #include <arpa/inet.h>
   4:  #include <err.h>
   5:  #define OUTSTR_SIZE 4096
   6:  extern "C"
   7:  {
   8:      const char* copyStr( const char* str )
   9:      {
  10:          char* s = (char*)malloc(strlen(str) + 1);
  11:          strcpy(s, str);
  12:          return s;
  13:      }
  14:      const char* IOSGetAddressInfo(const char *host )
  15:      {
  16:          if( NULL == host )
  17:              return copyStr("ERROR_HOSTNULL");
  18:          char outstr[OUTSTR_SIZE];
  19:          struct addrinfo hints, *res, *res0;
  20:          memset(&hints, 0, sizeof(hints));
  21:          hints.ai_family = PF_UNSPEC;
  22:          hints.ai_socktype = SOCK_STREAM;
  23:          hints.ai_flags = AI_DEFAULT;
  24:          printf("getaddrinfo: %s\n", host);
  25:          int error = getaddrinfo(host, "http", &hints, &res0);
  26:          if (error != 0 )
  27:          {
  28:              printf("getaddrinfo: %s\n", gai_strerror(error));
  29:              return copyStr("ERROR_GETADDR");
  30:          }
  31:          memset( outstr, 0, sizeof(char)*OUTSTR_SIZE );
  32:          struct sockaddr_in6* addr6;
  33:          struct sockaddr_in* addr;
  34:          const char* solvedaddr;
  35:          char ipbuf[32];
  36:          for (res = res0; res; res = res->ai_next)
  37:          {
  38:              if (res->ai_family == AF_INET6)
  39:              {
  40:                  addr6 =( struct sockaddr_in6*)res->ai_addr;
  41:                  solvedaddr = inet_ntop(AF_INET6, &addr6->sin6_addr, ipbuf, sizeof(ipbuf));
  42:                  strcat ( outstr, "ipv6|");
  43:                  strcat ( outstr, solvedaddr);
  44:              }
  45:              else
  46:              {
  47:                  addr =( struct sockaddr_in*)res->ai_addr;
  48:                  solvedaddr = inet_ntop(AF_INET, &addr->sin_addr, ipbuf, sizeof(ipbuf));
  49:                  strcat ( outstr, "ipv4|");
  50:                  strcat ( outstr, solvedaddr);
  51:              }
  52:              strcat ( outstr, "|");
  53:          }
  54:          return copyStr(outstr);
  55:      }
  56:  }
转载请注明:http://www.cppblog.com/sunicdavy战魂小筑

iosaddrinfo.h

   1:  #pragma once
   2:  extern "C"{
   3:      const char* IOSGetAddressInfo(const char *host );
   4:  }
  • C#层的处理假设多个地址中都是统一的地址类型,要么全是v4要么全是v6
    返回给定的host内多个IP地址, 可以供处理复杂的北网通,南电信问题

   1:  using System;
   2:  using System.Net;
   3:  using System.Net.Sockets;
   4:  using System.Runtime.InteropServices;
   5:  using UnityEngine;
   6:  using System.Collections;
   7:  using System.Collections.Generic;
   8:  public class IOSIPV6
   9:  {
  10:      [DllImport("__Internal")]
  11:      private static extern string IOSGetAddressInfo(string host );  
  12:      public static IPAddress[] ResolveIOSAddress(string host, out AddressFamily af)
  13:      {
  14:          af = AddressFamily.InterNetwork;
  15:          var outstr = IOSGetAddressInfo(host);
  16:          Debug.Log("IOSGetAddressInfo: " + outstr);
  17:          if (outstr.StartsWith ("ERROR")) 
  18:          {
  19:              return null;
  20:          }
  21:          var addressliststr = outstr.Split('|');
  22:          var addrlist = new List<IPAddress>();
  23:          foreach (string s in addressliststr)
  24:          {
  25:              if (String.IsNullOrEmpty(s.Trim()))
  26:                  continue;
  27:              switch( s )
  28:              {
  29:                  case "ipv6":
  30:                      {                        
  31:                          af = AddressFamily.InterNetworkV6;
  32:                      }
  33:                      break;
  34:                  case "ipv4":
  35:                      {
  36:                          af = AddressFamily.InterNetwork;
  37:                      }
  38:                      break;
  39:                  default:
  40:                      {
  41:                          addrlist.Add(IPAddress.Parse(s));
  42:                      }
  43:                      break;
  44:              }
  45:          }
  46:          return addrlist.ToArray();
  47:      }
  48:  }
转载请注明:http://www.cppblog.com/sunicdavy战魂小筑

参考链接

官方文档
https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html#//apple_ref/doc/uid/TP40010220-CH213-SW1

某人的解决方案
http://www.codeinsect.net/blog/2016/05/26/unity-ipv6-socket-%E6%94%AF%E6%8C%81%EF%BC%8C%E5%B7%B2%E6%B5%8B%E8%AF%95%E9%80%9A%E8%BF%87/
注意, 此方案中的方法可用, 但是地址并不能解决南北互通的问题

posted on 2016-06-16 14:18 战魂小筑 阅读(5205) 评论(0)  编辑 收藏 引用 所属分类: 游戏开发技术移动开发Unity3D

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理