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

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.)

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.

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.

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.

Related

How to specify the source port for an http request in iOS

I know that it's an unusual thing to need to do, but I need to specify the SOURCE port to be used in an outgoing http(s) request in iOS. I know that there are many different 'standard' ways to send http(s) requests -- from what I understand the most usual involve NSURLConnection and NSURLSession, but I couldn't see if I can specify the source port. Is it possible to somehow use a socket interface to create the socket and then use this socket with NSURLConnection or NSURLSession?
Or perhaps (as a hack) can one specify the ephemeral port range that my app can use (so I'll restrict it to a range of 5 or 10 ports)?
As a last grasping at straws: is there some ip masquerading or other rules that are available on the iOS device that the app could use to ensure that the source port is correct? (I suppose one could write a process which just does masquerading by hand to the correct fixed port -- essentially write a local http forwarding proxy -- is that my only possibility?)
I don't need any fancy feature or control of these http(s) requests except that they need to come from a certain very narrow range of port numbers.
thanks very much.
If you want to ask why I have such a stupid requirement, please feel free to ask privately -- but don't clutter up this question. THanks!!
I note that just a year ago, iOS: how to get the http connection's source port was asked, but that asked about READING the ephemeral port chosen by the system.
thanks

iOS - NSURLConnection connections to more than 5 different IPs over LAN

My app tries to determine the IP of a web server located on the same LAN when it starts up.
It works out the IP range to scan, and uses NSURLConnection objects with a 1 second time out to determine whether an IP is reachable, and if it is, try to call a service on it, if the service call is successful then we know we've found the correct IP.
The problem though is that the app cannot open more than 5 connections at a time, even though all the connections have different IPs to connect to. I would get about a dozen connections firing off but the rest will just report The request timed out. without ever leaving the device.
I have read that this restriction applies to NSURLConnection connections to a single IP address, but as I said, each connection has its own different IP.
I have also tried using the SCNetworkReachability to determine whether an IP is reachable but all it tells me is that the IP addresses on the LAN are reachable, in theory, without making an actual connection.
Are there reliable ways to connect to more IPs at a time?
Every operating system maintains a maximum number of sockets per process. I couldn't find an authoritative source for iOS, but it would make sense for Apple to keep that number very low and five seems to be a common answer by others trying this.
You may want to look at NSOperationQueue to manage the connections (see Asynchronous HTTP Client Using NSOperationQueue) or use AFNetworking to do all the real work.

How can I check that a computer can access a certain URL and send and receive e-mail?

With Delphi XE2, what is the most reliable method to detect if the computer is able to do the following things?
reach a specific website with HTTP which does not have a fixed IP address
send and receive e-mail with any local or remote e-mail client
There are too many factors involved (type of Internet connection, firewall/router rules, proxies, etc). The most reliable approach is to simply not try to determine the current state and just attempt the desired operation (perform the actual HTTP request, or the SMTP/POP3/IMAP operation, etc), and just be prepared to react to any errors. You can detect connection-related errors and prompt the user to check their Internet connection before retrying.
Use TIdHTTP.Get and try to download http://google.com.
Of course it depends on the definition of being connected to the internet. Sometimes web traffic (port 80) is blocked while other ports are open. Fortunately, nowadays most people are actually allowed to browse the web, since it also provides help with their daily activities. Google is probably one of the least firewalled websites with one of the highest uptimes.
But still, it's a lucky guess. Depending on what you need it for, you might as well just try your thing and see if it works. If not, apparently the computer was not properly connected, even if it could reach Google. :)
[edit]
Because of the discussion. InternetCheckConnection is a good alternative too, but it also checks the connection by pinging an actual server.
MSDN says
Use the InternetCheckConnection function to check the connection to
the Internet. It attempts to ping the server designated by the URL
that is passed to the function. If the FLAG_ICC_FORCE_CONNECTION flag
is set and the URL is NULL, the function checks to see if there is an
entry in the server database for the nearest server. If one exists,
the function pings that server
But since this function uses ping, it may be a bit faster than actually retrieving content. On the other hand, many firewalls actively refuse pings.

Send text messages between two computers through internet with delphi?

I want to write a app which will run on different computers and need all of then to communicate with each other like "utorrent" (peer to peer). This app only will send text messages.
How can I do this? I mean sending one message to remote computer on the internet?
I have a website and every app at start can send some information to it and find information of other apps on other computers (with PHP) but I do not know how address one computer through internet and send the data directly to that. I can find the ip address with PHP but it is the ip address of router (ISP).
How a message reaches a computer? I'm wondering about addressing every computer?
My brain really stuck here, I really appreciate any help. Thanks.
In a peer-to-peer network there's no centralized server for transmitting the data from one client to another, in this case the clients must be able to act as both the server and client. This means that either you'll have to be using UPnP like most modern torrent clients, which handles port forwarding in the router, or you'll have to manually forward a port to the computer in the router.
A centralized server (like a torrent tracker) is usually used to make the clients aware of each other's existence and tell them where to connect. This is where your PHP script comes in, though PHP might not offer the most effective way of doing this, assuming you're using it in combination with a webserver to serve the data though the http protocol.
As for actual text communication, you could use the Indy socket library for that. I found this example, basically which shows how to do it: http://www.ciuly.com/delphi/indy/indy-10-client-server-basic-demo/

How can I transload data between two delphi applications over internet?

Hi
let me make my question clear. Two people using my app are connected to the internet. Both have each other's IP and they want to chat (like Y!messanger) with each other.
I think I need to use Indy components; right? Which component should I use?
Thanks in advance
Have you looked at any of the demos on Indy's website yet?
In general, you are looking to create a "Client/Server" type application. A quick Google search for "indy client server example" pulls up lots of results, including this one: http://www.devarticles.com/c/a/Delphi-Kylix/A-Real-World-Client-Server-Application-in-Delphi/
In reality, this gets a lot more complicated when you have firewalls and NATs with private IP addresses. You will have to consider how your application will either get around or through these types of technologies.
Similar to what Scott said, I think that your biggest problem is getting them talking to each other. My computers at home go through a router, which blocks all incoming connection requests (i.e. requests to start a conversation between two computers) from the Internet. My computers can send connection requests OUT, and start a conversation that way, but unless you modify the router (port forwarding) my computers can not receive connection requests.
You need a server somewhere to which both people will connect, that can then relay messages back and forth. To get really tricky, once the connection is made to the server the two computers can then be put into direct contact, but that involves UDP packets and some clever magic.
You don't have to use Indy components, you just need anything that will handle communications over the network. Any HTTP or sockets network stack will do. Indy is the defacto standard for Delphi Win32.
To do network communications, you will need to create a listener object or service on machine A and a sender object on machine B to send a network message from A to B. To send a message from B to A, you will need a reverse path as well - 4 objects total to perform bidirectional comms. Some object wrappers hide this detail internally. I don't recall offhand whether Indy hides this or not.
It would probably be easiest if you use a common TCP/IP protocol for your machine to machine communications, such as HTTP. This will make it easier to get your connections through firewalls and proxies that frequently exist between arbitrary users. To avoid conflicting with any HTTP web services that might be running on either machine, you should use a custom port number with the IP address: 192.168.1.10:12345, not the standard HTTP web server port 80. This is what most of the IM clients do.

Resources