我在多设备应用程序上使用TIdHTTP组件(在Rad Studio Tokyo 10.2.3中构建)。我正在做的就是将文件下载到我的本地应用程序文件夹(iOS)。我想确保它适用于IPv6,但我没有看到TIdHTTP的“IPVersion”属性。我在rad studio中的其他indy组件上看到它(例如IdFTP)。
有没有办法在TIdHTTP组件的代码中设置IPVersion?下面是我用来下载文件的代码片段。如果在IPv4上失败,则应该尝试下一步:
UnicodeString LFileName = System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath(), "myfile.txt");
TFileStream* fs = new TFileStream(LFileName, fmCreate);
Form1->TIdHTTP->ConnectTimeout = 8000; // give it 8 seconds
Form1->TIdHTTP->ReadTimeout = 8000;
try
{
UnicodeString URL = "http://myservername.com/myfile.txt";
Form1->TIdHTTP->Get(URL, fs);
Form1->TIdHTTP->Disconnect();
// ShowMessage("Good download via IPv4");
}
catch(const System::Sysutils::Exception &)
{
try
{
Form1->TIdHTTP->Disconnect(); // clean up from IPv4 try
UnicodeString URL = "http://[myservername.com]/myfile.txt";
Form1->TIdHTTP->Get(URL, fs);
Form1->TIdHTTP->Disconnect();
// ShowMessage("Good download via IPv6");
现在我只是在域名周围添加括号,希望这对IPv6有用......我不确定,直到我能够获得真正的IPv6网络设置(处理它)。
更新:我刚接到Apple Store接受使用此方法的应用程序,显然它通过了IPv6测试。 FYI
答案 0 :(得分:0)
我找到了this discussion,其中Remy Lebeau说:
TIdHTTP仅从URL本身解析IP版本信息,因此,如果您需要向IPv6目标(IP地址或主机名)发送请求,则必须通过包装URL的主机名部分来告知TIdHTTP使用IPv6。方括号,例如:
s := idHTTP.Post('http://[IPv6 address or hostname]/resource', ...);
否则TIdHTTP会使用IPv4。
在使用IPv6地址文字时,这个括号内的语法是必需的 URL,根据RFC 2732和3986.但是当使用主机名时,有 没有这样的语法要求。连接到主机名需要DNS查找 发现主机的可用IP地址及其各自的IP版本,然后根据需要连接到这些地址,直到成功为止。
Indy目前没有实现这种连接模式。它首先 根据客户端的IPVersion属性分配一个套接字,THEN执行 一个适合该IPVersion的DNS请求,然后最终连接到 DNS报告的第一个IP地址。这是Indy的已知限制,其中 需要重新设计Indy的内部逻辑来修复。但是,它可以 通过执行在大多数Indy客户端组件中手动处理 提前进行自己的DNS查找,然后循环遍历结果,设置Indy的Host和IPVersion属性,并在每次循环迭代时调用Connect()。
但是,TIdHTTP是一种特殊情况,因为它从请求的URL派生Host和IPVersion值,覆盖调用代码可能手动设置的任何内容。但是,也正是因为这种模型可能允许更新TIdHTTP以在内部执行自己的DNS循环,而无需重写所有Indy的客户端组件以进行匹配。除了Indy当前没有实现返回主机名的所有IP地址的功能,只有特定版本的第一个IP地址。在以跨平台方式将此功能添加到Indy之前,无法更新TIdHTTP以自动检测IPv4 / IPv6主机。
因此,这确认了我的方法应该工作(首先尝试IPv4,然后尝试IPv6,如果失败)使用括号。
此外,我编辑了我的代码,在尝试使用IPv6之前显示“断开连接”,以防IPv4出现问题。