iOS - random "Cannot connect to host" with 3G
Asked Answered
L

3

8

I am working on an iOS application which works as a thin client for a bussiness server. There is a lot of requests sent to the server, a lot of data downloaded.

I don't use any fancy request frameworks, just asynchronous NSURLConnection with a delegate.

The application usually works very well with both wifi and 3G BUT

some users report random disconnects when using 3G (in USA). All request are okey but once in a while a request fails with "Cannot Connect to Host" (-1004) error.

This affects user experience a lot.

Some facts:

  1. It doesn't happen on wifi
  2. Users report that it doesn't happen with other applications when using 3G.
  3. It's not a timeout issue, the error appears 0.3-1.0 secs after starting the connection.
  4. We were not able to reproduce the problem using traceroute.
  5. Using SCNetworkReachability the host appears to be reachable (I know the limitations of this API).

Question What could be the cause of the problem? What connection properties can differ with 3G and wifi? How can I debug it?

Currently the only solution I see is to try to send the request again if the previous request has failed. However, I would like to find the cause of the problem first.

EDIT The problem was probably caused by one of our routers. IT guys are still inspecting the problem.

Languor answered 31/7, 2012 at 20:22 Comment(1)
lets see your code. I know your unit tests pass and all but just in case ;)Schizomycete
H
5

All error codes can be found in the Apple documentation under the section

CFNetwork Error Codes Reference

The code -1004 is described only as

kCFURLErrorCannotConnectToHost

The connection failed because a connection cannot be made to the host. Available in OS X v10.6 and later. Declared in CFNetworkErrors.h.

It basically means that the user has a connection (he is not on flightmode, data traffic is turned on, and his phone is registered in the network, you had a valid URL etc) but was actively prevented from connecting to the server. If the server was not responding, you would have had something more like a time out error after a longer waiting time, as you described. This kind of error is probably caused by something preventing the traffic to the server and can for example happen if the user is behind a firewall or a proxy.

The issue could actually be caused by the provider, especially if you have no issues with some users, and random issues with others.

As some other poster said, you could try to ask your users about their service provider, and more details about their location, or what they were doing when they got the error (like sitting in a vehicle or having bad reception in the countryside)

If you can't find any patterns, and if the error really just occur randomly and only for some users, and just sometimes, I would just consider it to be another unevitable issue that can be caused by the fact that mobile phones are never guaranteed to be connected all the time, and that some cellphone providers may not always deliver 100% of all packages that should be delivered out there... what you need to do then is just to handle the error.

Build away the error by simply retrying, and not showing it to the user, at least not until after a sufficient amount of retries.

One last thing to consider:

If you send lots and lots of requests from your app, and lots of data, make sure that you are not "overconsuming" by spamming huge amounts of unfinished requests. This could cause the server or some proxy server on the way to refuse your request because it is too busy answering your other request. A refused request could cause an error like that. Make sure to send a reasonable amount of requests so that your user's device has time to "breathe".

Let your retry-scheme be a smart one where you start out by retrying a bunch of times within shorter time, and if it keeps failing, increase the time span to the next retry.

Heinous answered 3/8, 2012 at 14:25 Comment(4)
Although this answer doesn't tell me anything new, it's probably the best answer. I will add retries.Languor
Checking the return code of a hung network request accomplishes nothing. Since its hung.Schizomycete
Not only that but you would have to build a thread, a runloop, a timeout and a retry count for every network request in your app to accomplish what your saying...not the right solution.Schizomycete
It is not hung since it has failed with errors. When the request fails it means it has given up. If you want the data you have to send a new request. If there is still reachability, no reason not to do it again. You don't have to do it with hundreds of threads and a handler for each request, if you are fighting with many requests you can write code to centralize and handle them in one place and make sure they behave nicely. Just checking reachability and then bombing away requests because you're assuming it will work is not a very stable solution.Heinous
S
3

I'd revisit the assumption that it's only affecting your application. There's lots of ways users might only see problems with your application even if the problem is with their Internet connection. For instance, perhaps the other applications retry transparently - users would simply see slower update speeds. Or perhaps dropped connections simply don't matter to the other applications.

Have you asked the affected users which provider they are using? If all of them use the same mobile network, that would indicate it's a problem with the network rather than your application.

Straiten answered 3/8, 2012 at 14:0 Comment(0)
F
2

It would seem to me that the reason for this is simply down to the nature of cellular data and internet access. As you might know, when you are using a cellular connection, sometimes - especially if you are moving, the connection will switch network as it changes broadcast towers.

You mention that you are downloading a lot of data and at close intervals, I would assume this is making your application more prone to this problem, and I wouldn't accept for one second that this wouldn't happen for other apps - it's about timing.

Feebleminded answered 3/8, 2012 at 14:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.