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.
Related
Short version: How would you recommend going about connecting a client to a server that are on the same local network, without manually entering the ip, when broadcast is disabled?
Further details: I am working on an educational multiplayer game for children. Many schools appear to be blocking broadcasting for security reasons. The children will be rather young, so it could be difficult for them and error-prone to have to enter the IP manually. They will all be in the same room and will all see the server screen. The game is made in Unity (C#).
Potential solutions: Here's what I thought about:
Connecting both the local server and clients to an external server, communicating the local server ip through the clients through the external server, then connecting directly and disconnect from the server. Not ideal because of the extra hosting costs.
Send a regular UDP message periodically to all ips on the subnet? This will probably be picked up by any decent firewall and blocked though, right?
Putting a QR code on the server that kids would take a picture of with the client app and have it connect that way? May be more of a hassle.
Having the server play random tones corresponding to numbers that the client is listening for? (Speakers may not always work though)
Sounds like the first one is the most sane and easy solution. Do you have any other ideas on what someone in this situation could try?
Is UDP multicast possible?
If yes then a common solution is that all participants join the same multicast group and the server listens on a well known port. If a client wants to know the address of the server it sends a packet to the multicast group, which is received by the client and answered with another packet, which then can be used by the client to determine the servers address.
In addition to that servers can also announce their presence in regular intervals by sending a suitable message to the multicast group.
What I can think of is an ad-hoc communication protocol between all the devices. Say you have 1 server and 10 clients. All the devices should run a service(say server-discovery) that binds to a fixed port say 9999. Now any time the client wants to connect to the server and doesn't know the IP, it starts a scan. Loops through different IPs and tries to connect to 9999. If it manages to hit, it asks for the server IP. In case it manages to hit the server it will get the IP since the server knows it's own IP and the client will maintain the server IP in a cache. If the client hits another client. It can ask for the server IP. It the other client knows the IP it will share the info else decline.
I agree there is a lot of overhead, but I think this will be robust unlike sound and would reduce cost of printing QRs everytime.
on the local network the traffic is direct from host to host.
I don't understand which devices is blocking local broadcasts.
if there aren't too many peers on the LAN ( less then 100 ), I think udp broadcasts work fine and you dont pollute the network.
to have an idea of your "pond", I suggest you to sniff your local traffic.
there are many broadcasts : arp, windows, ipp, dropbox...
I would like to understand networking services with a large user base a bit better so that I know how to approach a project I am busy with.
The following statements that I make may be incorrect but they still lead to the question that I want to ask...
Please consider Skype and TeamViewer clients. It seems that both keep persistent network connections open to their respective servers. They use these persistent connections to initiate additional connections. Some of these connections are created by means of Hole Punching if the clients are behind NATs. They are then used for direct Peer-to-Peer communications.
Now according to http://expandedramblings.com/index.php/skype-statistics/ there are 300 million users using Skype and 4.9 million daily active users. I would assume that most of that 4.9 million users will most probably have their client apps running most of the day. That is a lot of connections to the Skype servers that are open at any given time.
So to my question; Is this feasible or at least acceptable? I mean, wouldn't it be better to not have a network connection open while idle and aspecially when there are so many connections open to the servers at once? The only reason I can think is that it would be the only way to properly do Hole Punching. Techically, how is this achieved on the server side?
Is this feasible or at least acceptable?
Feasible it certainly is, you mention already two popular apps that do it, so it is very doable in practice.
As for acceptable, to start no internet authority (e.g. IETF) has ever said it is unacceptable to have long-lived connections even with low traffic.
Furthermore, the only components for which this matters are network elements that keep connection/flow state. These are for sure the endpoints and so-called middleboxes like NAT and firewalls. For the client this is only one connection, the server is usually fine tuned by the application developers (who made this choice) themselves, so for these it is acceptable. For middleboxes it's simple: they have no choice, they're designed to just work with all kind of flows, including long-lived persistent connections.
I mean, wouldn't it be better to not have a network connection open while idle and aspecially when there are so many connections open to the servers at once?
Not at all. First of all, that could be 'much' slower as you'd need to set up a full connection before each control-plane call. This is especially noticeable if your RTT is big or if the servers do some complicated connection proxying/redirection for load-balancing/localization purposes.
Next to that this would historically make incoming calls difficult for a huge amount of users. Many ISP's block/blocked unknown incoming connections from the internet by means of a firewall. Similar, if you are behind a NAT device that does not support UPnP or PCP you can't open a port to listen on for your public IP address. So you need it even aside from hole-punching.
The only reason I can think is that it would be the only way to
properly do Hole Punching. Techically, how is this achieved on the
server side?
Technically you can't do proper hole-punching as soon as the NAT devices maintain a full <src-ip,src-port,dest-ip,dest-port,protocol> (classical 5-tuple) flow match. Then the best you can do with 'hole punching' is set up a proxy between peers.
What hole-punching relies on is that the NAT flow lookup is only looking at <src-ip,src-port,protocol> upstream and <dest-ip,dest-port,protocol> downstream to do the translation. In that case both clients just set up a connection to the server, their ip and port gets translated and the server passes this to the other client. The other client can now start sending packets to that translated <ip,port> combination which should work because NAT ignores the server's ip/port. But even if the particular NAT would work like this, some security device (e.g. stateful firewall) might detect session hi-jacking and drop this anyway.
Nowadays you rather use UPnP to open up a port to listen on your public IP which is much easier if supported.
I spent the last two days reading each StackOverflow questions and answers (and googling of course) about Indy TCP and UDP protocol in order to decide which one should I use in my communication method between my User Application and my Windows Service.
From what I saw so far, UDP is the easiest and the only one I managed to work to receive broadcast messages from TidUDPClient (I did not testes the response back yet). And I also noticed that TCP is a bit more complicated with it's thread loop.
But since everywhere I am told UDP is not reliable, UDP is not reliable... I begin to wonder if it's not better to use TCP anyway.
My User Application will be running on many machines, and the Service will be running in one of them, sharing one IP with a Client, or in a dedicated machine, depending on my client's funds. So, should I really be worried about UDP data loss possibilities?
I need broadcast capabilities so my server advises all clients at once about Application updates, and of course, if my the Client Application does not know in which IP the Service/Server is, it will send a broadcast call to be told where the server is. Is that applicable to TCP?
The messages I am sending are requests for users access confirmation, users privileges, and application executable file updates, since the main application can't update itself.
Those messages are encrypted like below, and they might bet bigger sometimes.
e86c6234bf117b97d6d4a0c5c317bbc75a3282dfd34b95446fc6e26d46239327f2f1db352b2f796e95dccd9f99403adf5eda7ba8
I decided to use them both!
Simple use case:
In order to communicate with TCP prococol you have to establish a connection which you can have only if you know IP and Port on both ends.
If you do not have that information when you load your Application, then you use the UDP to Broadcast your IP address and your intention to find the/a Server. You may try about 5 times before you raise the user an error telling that you did not find the Server or that the Server is down.
Sending that message in UDP will (one time or other) reach the UDP ear of the Server, which will now know the IP from the lonely Client's IP and will now begin a proper connection via TCP to be read talk about the critical messages of the Application.
What do you think of that approach?
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.
so I'm making an iOS app, but this is more of a general networking question.
So what I have is one phone that acts as the server and then a bunch of phones connect to the phone as the client. Basically it's a game/music sharer.
It's kind of hard to really get into the semantics of it, but that isn't important.
What is important is that the server and client are repeatedly sending each other commands and positions rapidly over a TCP connection, and sometimes the client wants to send the server a music file (4MB usually) to play as the music.
The problem I initially encountered was that when sending the large file, it would hang the sending of commands from the client to the server.
My naive solution was to create another socket to connect to the server to send the file to the server, the server would check the IP of the new socket, and if it has the IP of an existing connection then it would just tie it to that connection, receive the file, and then disconnect the socket.
But the problem with this is that it takes a 1-2 second delay for the socket to connect, and I'm aware that there are man-in-the-middle attacks that can occur.
Is there a more elegant solution to this problem?
I would not call your solution naive, this is largely how FTP works, separating data and control paths is a good design pattern in my view.
I wouldn't worry about the man in the middle thing. If you wanted, you could add a command to the client that it responds to over the data connection with a secret the server supplies, this would let you associate the connections without using the ip addressing.
If the delay is a problem then why not establish both connections at the start, the overhead of a few tcp connections on an operating system is not usually significant.
You could also use the two connections for both commands and data, alternating between them. Since both the server and client know when a connection is busy they can choose to use the idle one. The advantage of this is that it will keep both connections busy to ensure they are both known to be working.
You probably should also use a different thread for each socket but I suspect you are doing this since it won't work too well without it.