我怎样才能得到用于连接 iOS 的确切 IP 地址?

How can I get the exactly ip address which used to connect in iOS?

我使用域名创建了一个请求,例如 http://www.google.com。但是我怎样才能得到框架用来连接服务器的确切 ip 地址呢?

我知道gethostbyname方法或者nslookup方法可以给我们地址,但是由于ip地址是动态分配的,可能我当时请求的ip地址和这些不一样返回的方法。

请问有什么方法可以获取真实请求的ip地址吗? (我想以编程方式获取 ip,而不是使用 tcpdump 等)

您的浏览器或您用来发出 HTTP 请求的任何其他工具将在发出请求时查找地址。在任何合理的系统上,他们将使用与 gethostbyname 相同的方法查找地址,除了浏览器中可能有本地缓存​​(您通常可以关闭或清除)。

该请求可能会收到重定向响应,以向不同的位置发出相同的请求。这些通常用于负载平衡等。我可以看到您能够找出这些背后的 'ultimate destination' 的唯一直接方法是以编程方式发出请求并记录任何重定向的详细信息,当然,负载平衡的本质是您每次都可能重定向到稍微不同的服务器。

顺便说一句,这与'dynamic allocation of IP addresses'无关。如果 www.google.com 的 IP 地址发生变化,很可能不是因为同一台服务器分配了不同的 IP 地址,而是因为请求被定向到不同的机器。

当您在这里说 "which the framework used" 时,我假设您指的是 NSURLSessionNSURLConnectionUIWebViewWKWebView。每一种情况都略有不同,但在所有这些情况下,答案是直接不可能(但见下文;间接可能)。您无权访问它们中的任何一个使用的底层套接字。它们都使用连接池,即使您可以获得 "the socket.",这也会使事情稍微复杂化。在 UIWebViewWKWebView 的情况下,对 www.google.com 的单个请求可能会生成多个独立连接,每个连接都可能与不同的 IP 地址交互。

(我对你想要做的事情有点着迷。由于负载平衡,单个 IP 地址并不意味着单个服务器,因此 IP 地址仅比 CNAME 更具识别性。混合在反向代理中....)

如果您需要这种访问权限,您必须自己管理套接字。对于除 WKWebView 之外的所有系统,这通常都是可能的。我假设您已经知道(或可以轻松学习)如何使用 CFSocketCFHTTPMessage 创建套接字并执行 HTTP。 CFNetwork Programming Guide 对此进行了广泛介绍。如果您已经创建了套接字,您可以使用 CFSocketCopyPeerAddress 来检查您真正连接到的主机。这就是你想要的作品。

鉴于您能够创建这种套接字并自己管理它,您可以使用 NSURLProtocol 将其连接到主要的 URL 加载程序(WKWebView 除外)。有关快速介绍和一些示例代码,请参阅 Drop-in Offline Caching for UIWebView (and NSURLProtocol)。您只需要接受请求并使用 CFSocket 自己制作,让您有机会看到您连接到的确切端口。

如果您使用 NSURLSession 获得 URLSessionStreamTask,您可以使用 -captureStreams 捕获底层流。这将调用 -URLSession:streamTask:didBecomeInputStream:outputStream: 委托方法,为您提供 NSInputStreamNSOutputStreamNSInputStream 是免费桥接到 CFReadStreamRef 并使用 CFReadStreamCopyProperty() 和常量 kCFStreamPropertySocketNativeHandle 为您提供本机套接字句柄,您可以将其传递到 getpeername()。对于上传、下载和数据任务,似乎不存在这种可能性。