蘋果ios應用的網路ipv6適配攻略
阿新 • • 發佈:2018-12-22
蘋果要求在2016年6月1日後新的app必須支援ipv6網路, 技術發展靠蘋果果然沒錯, 但開發者還是要開始忙起來了
這裡介紹下Unity3D的適配的一些經驗
基本注意點
- ios ipv6適配無需修改伺服器, 也就是說, 如果你的伺服器依然是ipv4的也是可以使用的
- 蘋果的適配方案是將ipv4的地址轉換為ipv6, 到了路由層再轉回去繼續利用ipv4網路傳輸
測試網路環境搭建
-
無需路由器支援ipv6, 但貓(modem)必須要支援ipv6. 因為現在大多數都是光貓
以下截圖是光貓管理端
光貓裡的ipv6支援預設是關閉的, 所以需要手動開啟, 按預設值配置即可 -
請確認mac os系統必須是osx 10.11以後的版本才可以開啟NAT64
- 預設連線上wifi時看連線資訊時, 一般只會有紅色DNS地址或者根本不顯示
- 只有在第一次訪問網路, 例如開啟瀏覽器進入任意網站時, 才會顯示上面的幾條資訊
- 如果只有DNS沒有IP地址和子網掩碼, 一般是光貓沒有開啟ipv6的DHCP, 沒有分配IP
- 還有一種測試ipv6 DHCP是否正常工作的方法: 關閉NAT64時可以上網, 但開啟NAT64無法上網
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地址|
iosaddrinfo.mm
1: #include <sys/socket.h>
2: #include <netdb.h>
3: #include <arpa/inet.h>
4: #include <err.h>
5: #define OUTSTR_SIZE 40966: 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: else46: {
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: }
iosaddrinfo.h
1: #pragma once2: 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 IOSIPV69: {
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: }