Reputation: 1953
I created a request using a domain name, e.g., http://www.google.com
. But how could I get the exactly ip address which the framework used to connect to the server?
I knew that the gethostbyname
method or the nslookup
method could give us the address, but since the ip address is dynamic allocated, maybe the ip address I request that time is different with these methods returned.
So is there a way for me to get the real requested ip address? (I wanted to get the ip programmatically, rather than using tcpdump, etc.)
Upvotes: 7
Views: 2934
Reputation: 133159
In case you are using NSURLSession
to obtain a URLSessionStreamTask
, you can capture the underlying streams using -captureStreams
. This will invoke the -URLSession:streamTask:didBecomeInputStream:outputStream:
delegate method, giving you a NSInputStream
and a NSOutputStream
. NSInputStream
is toll-free bridged to CFReadStreamRef
and using CFReadStreamCopyProperty()
and the constant kCFStreamPropertySocketNativeHandle
provides you with the native socket handle, which you can pass into getpeername()
. For Upload-, Download- and DataTasks, no such possibility seems to exist.
Upvotes: 0
Reputation: 299545
When you say "which the framework used" here, I assume you mean NSURLSession
, NSURLConnection
, UIWebView
, or WKWebView
. Each of those is a slightly different situation, but in all of them, the answer is that it's not possible directly (but see below; it's possible indirectly). You have no access to the underlying sockets that any of them use. All of them use connection pooling, which complicates things slightly even if you could get "the socket." And in the case of UIWebView
and WKWebView
, a single request to www.google.com
may generate several independent connections, each of which could potentially interact with a different IP address.
(I'm a bit fascinated about what you're trying to do. Due to load balancing, a single IP address doesn't mean a single server, so IP addresses are only marginally more identifying than CNAMEs. Mixing in reverse proxies....)
If you need this kind of access, you have to manage the socket yourself. That's generally possible with all of the systems except WKWebView
. I'll assume that you know already (or can easily study) how to create a socket and perform HTTP using CFSocket
and CFHTTPMessage
. This is extensively covered in the CFNetwork Programming Guide. If you've created the socket, you can use CFSocketCopyPeerAddress
to check what host you really connected to. That's the piece you wanted.
Given you are able to create this kind of socket and manage it yourself, you can hook that into the major URL loaders (except WKWebView
) using an NSURLProtocol
. See Drop-in Offline Caching for UIWebView (and NSURLProtocol) for a quick introduction and some sample code. You just need to take the request and make it yourself with CFSocket
, giving you the chance to see the exact port you're connected to.
Upvotes: 1
Reputation: 5837
Your browser or whatever other tool you use to make a HTTP request will look up the address at the time of doing the request. On any reasonable system, they will use the same method for looking up the address as gethostbyname
does, except that there might be local caching in the browser (which you can usually turn off or clear).
The request might get a redirection response to make the same request to a different location. These are often used for load balancing, etc. The only straightforward way I can see that you would be able to find out the 'ultimate destination' behind these, would be to make the request programmatically and record the details of any redirections, Of course, it is the nature of load balancing that you might redirected to a slightly different server each time.
This has nothing to do with 'dynamic allocation of IP addresses' by the way. If the IP address of www.google.com
changes, it is likely to be not because the same server has been allocated a different IP address, but because requests are being directed to a different machine.
Upvotes: 1