Delphi iOS IPv6 麻烦。请确保您的应用与 IPv6 网络兼容

Posted

技术标签:

【中文标题】Delphi iOS IPv6 麻烦。请确保您的应用与 IPv6 网络兼容【英文标题】:Delphi iOS IPv6 trouble. Please ensure that your app is compatible with IPv6 networks 【发布时间】:2017-04-05 22:11:13 【问题描述】:

我无法将我的 ios 应用发布到 AppStore。

Delphi 10.1.2 Berlin,iOS64,Win 8.1。

我收到了来自苹果的下一条信息:

感谢您的回复。

请确保您的应用与 IPv6 网络兼容。

测试应用程序的 IPv6 兼容性的最简单方法是在 Mac 上设置本地 IPv6 网络。然后,您可以从 iOS 设备连接到网络以测试 IPv6 兼容性。

请按照支持 IPv6 DNS64/NAT64 网络中提供的分步说明进行操作。

有关支持 IPv6 网络的更多信息,请查看支持 IPv6-only Networks。


这是连接代码。

     if (FSocket<>nil) then
     begin
          if not FSocket.Connected then
          begin
               SetState(mwtrstDisConnected);
               FSocket.Free;
               FSocket:=nil;
          end
          else
              exit;
     end;

     FSocket:=TIdTCPClient.Create(nil);
     FSocket.Host:=FHost;
     FSocket.Port:=FPort;

//CheckCode


$ifdef KBMMW_USING_INDY_9_OR_NEWER
     FSocket.BoundPortMin:=FMinClientPort;
     FSocket.BoundPortMax:=FMaxClientPort;
$endif

$IFDEF KBMMW_USING_INDY_10
     FSocket.ReadTimeout:=RequestTimeout*1000;
     FSocket.ConnectTimeout:=ConnectTimeout*1000;
$ENDIF
$IFDEF KBMMW_USING_INDY_8_00_23
     FSocket.Connect;
$ELSE
 $IFDEF KBMMW_USING_INDY_9
     FSocket.Connect(ConnectTimeout*1000);
 $ELSE
     FSocket.Connect;
 $ENDIF
$ENDIF
     DoConnected(Info);

在我看来,我必须在 //CheckCode 位置插入下一个代码。

  TIdStack.IncUsage;
  IdURI := TIdURI.Create('195.34.x.x');
  try
    try
      ss := GStack.ResolveHost(IdURI.Host, TIdIPVersion.Id_IPv6);
      IdURI.IPVersion := TIdIPVersion.Id_IPv6;
    except
      IdURI.IPVersion := TIdIPVersion.Id_IPv4; // Just in case.
    end;

    //ShowMessage(ss);
  finally
    FreeAndNil(IdURI);
    TIdStack.DecUsage;
  end;

但此代码 (GStack.ResolveHost) 在 iOS 上不起作用。

如何解决?

【问题讨论】:

“在 iOS 上不起作用”不是有用的错误描述。它怎么行不通?它会给你一个错误吗?它会给你带来意想不到的结果吗?它什么都不做吗?你的应用程序崩溃了吗?您需要对此类事情进行具体说明。 在我看来,设置Id.URI := TIdURI.Create('195.34.x.x');是注定要失败的,因为那是一个IPv4地址,所以它显然不能解析为IPv6。这就是你所说的不起作用吗? 肯是对的。让ResolveHost()(在 iOS 上工作)使用 IPv6 查找来解析 IPv4 地址是没有意义的。请注意,Indy 10 可以枚举本地分配的 IP 并报告它们是 IPv4 还是 IPv6,因此可以检测设备连接到 IPv6 网络还是 IPv4 网络。 是真的,Id.URI := TIdURI.Create('195.34.x.x'); 和 ResolveHost() 函数有问题。以及如何检测设备是否连接到 IPv6 以及下一步(如果已连接)如何将 IPv4 地址转换为 IPv6?你能展示一些作品演示吗? 你为什么还要使用TIdURI?如果您有一个 IP 地址,只需将其直接分配给Host 并相应地设置IPVersion(Indy 中有几种方法可以检测字符串是 IPv4 还是 IPv6 地址,例如 @987654328 @ 班级)。要将 IPv4 地址转换为 IPv6 地址,您必须将其重新编码为 IPv4 映射的 IPv6 地址。 Indy 没有这方面的功能,但它可以像在 IPv4 地址前添加 '::ffff:' 一样简单('195.34.x.x' -> '::ffff:195.34.x.x'),但这并不能解决您的潜在问题。 【参考方案1】:

试试类似的方法:

FSocket := TIdTCPClient.Create(nil);
FSocket.Host := FHost;
FSocket.Port := FPort;

$IFDEF KBMMW_USING_INDY_9_OR_NEWER
FSocket.BoundPortMin := FMinClientPort;
FSocket.BoundPortMax := FMaxClientPort;
$ENDIF

$IFDEF KBMMW_USING_INDY_10
FSocket.ReadTimeout := RequestTimeout*1000;
FSocket.ConnectTimeout := ConnectTimeout*1000;

// check if connecting to an IPv4/IPv6 address directly...
if GStack.IsIP(FHost) then // only checks for IPv4 right now
begin
  FSocket.IPVersion := Id_IPv4;
  FSocket.Connect;
end
else if MakeCanonicalIPv6Address(FHost) <> '' then
begin
  FSocket.IPVersion := Id_IPv6;
  FSocket.Connect;
end
else begin
  // connecting to a hostname, try IPv6 first, then fallback to IPv4...
  try
    FSocket.IPVersion := Id_IPv6;
    FSocket.Connect;
  except
    FSocket.IPVersion := Id_IPv4;
    FSocket.Connect;
  end;
end;
$ELSE
  // only IPv4 is supported...
  $IFDEF KBMMW_USING_INDY_9
FSocket.Connect(ConnectTimeout*1000);
  $ELSE
FSocket.Connect;
  $ENDIF
$ENDIF

DoConnected(Info);

或者:

var
  LIPAddress: TIdIPAddress;
  LLocalIPs: TIdStackLocalAddressList;
  TryIPv4, TryIPv6: Boolean;
  I: Integer;

...

FSocket := TIdTCPClient.Create(nil);
FSocket.Host := FHost;
FSocket.Port := FPort;

$IFDEF KBMMW_USING_INDY_9_OR_NEWER
FSocket.BoundPortMin := FMinClientPort;
FSocket.BoundPortMax := FMaxClientPort;
$ENDIF

$IFDEF KBMMW_USING_INDY_10
FSocket.ReadTimeout := RequestTimeout*1000;
FSocket.ConnectTimeout := ConnectTimeout*1000;

LIPAddress := TIdIPAddress.MakeAddressObject(FHost);
if LIPAddress <> nil then
begin
  // connecting to an IPv4/IPv6 address...
  FSocket.IPVersion := LIPAddress.AddrType;
  LIPAddress.Free;
  FSocket.Connect;
end else
begin
  // connecting to a hostname...

  TryIPv4 := False;
  TryIPv6 := False;

  LLocalIPs := TIdStackLocalAddressList.Create;
  try
    GStack.GetLocalAddressList(LLocalIPs);
    for I := 0 to LLocalIPs.Count-1 do
    begin
      case LLocalIPs[I].IPVersion of
        Id_IPv4: TryIPv4 := True;
        Id_IPv6: TryIPv6 := True;
      end;
    end;
  finally
    List.Free;
  end;

  if TryIPv6 then
  begin
    try
      FSocket.IPVersion := Id_IPv6;
      FSocket.Connect;
      TryIPv4 := False;
    except
      if not TryIPv4 then
        raise;
    end;
  end;

  if TryIPv4 then
  begin
    FSocket.IPVersion := Id_IPv4;
    FSocket.Connect;
  end;

  if not (TryIPv4 or TryIPv6) then
    raise Exception.Create('Not connected to an IPv4 or IPv6 network');
end;
$ELSE
  // only IPv4 is supported...
  $IFDEF KBMMW_USING_INDY_9
FSocket.Connect(ConnectTimeout*1000);
  $ELSE
FSocket.Connect;
  $ENDIF
$ENDIF

DoConnected(Info);

请注意,一旦 Indy 实现了以下功能,这种情况将变得更容易处理,但我认为这还有一段路要走:

Support round-robin DNS (support connecting to IPv4/IPv6 hostnames)

【讨论】:

Remy,非常感谢您的演示代码和帮助。我进行了更新并将其发送给 Apple 并期待一个结论。 嗯。第一个版本有效,但对我没有帮助。来自 Apple ->“要解决此问题,请在连接到 IPv6 网络的设备上运行您的应用程序(所有应用程序必须支持 IPv6)以识别任何问题,然后修改并重新提交您的应用程序以供审核。”会做第二个版本。 @Bum 为什么不呢?您遇到的实际问题是什么?你根本没有提供任何有用的细节。只是说“ResolveHost() 不起作用”并不能解释任何事情。为什么它不工作?你有错误吗?为什么 Apple 会拒绝您的应用程序?你做了苹果告诉你做的事吗? "设置本地 IPv6 网络 ... 测试 IPv6 兼容性" 没有错误。该程序通过互联网运行,但苹果不接受,我收到一条消息:在连接到 IPv6 网络的 Wi-Fi 上运行 iOS 10.3.1 的 iPad Air 2 和 iPhone 6s 上查看时,我们发现您的应用程序中有一个或多个错误.具体来说,当我们尝试扫描 QR 码时,您的应用程序产生了一条错误消息。有关详细信息,请参阅随附的屏幕截图。后续步骤 要解决此问题,请在连接到 IPv6 网络的设备上运行您的应用(所有应用都必须支持 IPv6)以确定任何问题,然后修改并重新提交您的应用以供审核。 我无法测试它,因为我的 mac mini 不支持 NAT64/DNS64 选项。我正在寻找其他测试方法。

以上是关于Delphi iOS IPv6 麻烦。请确保您的应用与 IPv6 网络兼容的主要内容,如果未能解决你的问题,请参考以下文章

由于 ipv6 将应用程序上传到苹果商店时出现问题

提升iOS审核通过率之“IPv6兼容测试”

当我们执行以下操作时,您的应用程序在运行 iOS 11.1 并连接到 IPv6 网络的 iPad 和 iPhone 上崩溃:

违反设备和网络滥用政策

与 ipv6 连接相关的 iOS 应用被苹果拒绝

指南 2.1 - 性能 在我们审核期间,您的应用在运行 iOS 11.2.5 并连接到 IPv6 网络的 iPad 或 iPhone 上崩溃