I am using NSURLConnection to communicate with a web service on my LAN. When using the Xcode Simulator everything works as expected. However, when using an iPhone the connection mostly times out (but not always).
The iPhone is connected to the LAN via wifi. I can consistently browse the web server (which is hosting the web service) using Safari.
However, the app mostly fails. It returns in the didFailWithError function reporting "The request timed out".
The app will intermittently succeed (behaving exactly as expected). I can see no pattern for success or failure. It may fail several times and then succeed and then fail again (without restarting the app). I estimate a 90%+ failure rate.
The web service always receives the request and always responds. It appears the failure happens with the device not receiving or handling the response.
I can see no obvious problem with my network. Certainly there is no IP address clash.
I am completely new to apps, Apple, Xcode and iPhone. So this could be something really very obvious to you. Any ideas what I could look at to resolve this?
The environment I'm currently using for development is as follows:
Mac OS X (10.7.4)
Xcode 4 (targetting 4.3)
iPhone 3GS (5.1.1)
Obviously I cannot give you the absolute answer, but can hopefully help you track the problem down.
First, you want vet your web service. Put a JPEG image in a public Dropbox folder. Now try to download that image with your code as well as view it with Safari. If Safari works but your code does not, then you know your code is the problem.
If both fail then the phone may have a bad transceiver, or your WIFI network may be flakey. Take the phone to some public WIFI location and redo the test. If both still fail on a second network, the phone is probably defective.
If in all cases Safari works but your code does not, then please post as much of your code as possible. Also, if using the asynchronous interface, are you getting redirected? Asked for credentials? Etc. I would be inclined to add every NSURLConnection delegate method and at least add a log so you know what's going on - that is log all responses. You can also get the html return code from the response:
assert([response isKindOfClass:[NSHTTPURLResponse class]]);
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
htmlStatus = [httpResponse statusCode];
if(htmlStatus != 200) NSLog(#"Server Response code %i", htmlStatus);
Related
I'm having an issue that's incredibly hard to debug. If my app is using WiFi and it sits idle for around 30 minutes, sometimes when I wake it up, the NSURLConnection no longer responds. Requests are sent, but never return.
At first, I thought this was a memory bug with the instances being released too early and thus never returning a response. However, if I put the app in the background, go into settings, turn off WiFi so 3G is used exclusively, and return to the app, the internet connection magically comes back to life and all pending NSURLConnections return and complete.
Obviously this is an issue for people using WiFi. Is this really a WiFi issue, or am I missing something? Going to another app like Safari, using the WiFi radio and returning to my app doesn't solve the problem - connections still don't return. I've traced this with Xcode and I'm running out of ideas.
Also 'Application Uses WiFi' Info.plist flag is set to ON and this is firmware 5.1.
is 'Application Uses WiFi' the same as UIRequiresPersistentWiFi?
Update: This has nothing to do with the Wifi flag - it can die within 5 minutes. So far, I've only been able to duplicate it on my iPhone 4s with 5.1 firmware. It's not really a solution, but I'm erasing the phone to try it with a fresh install to see if that has any effect. I have verified that NSURLConnection is always called on the main thread, and set breakpoints at connection:failedWithError: and connection:didReceiveResponse:. When the connection dies, none of these return until I disable and re-enable WiFi, and then all return at once. This happens on a local server as well, and the server still returns if I ping it with a web browser.
For any others running into this issue, it's due to TestFlight v1.0 and below:
Why does NSURLConnection fail to reach the backend?
Are you actually transmitting/receiving any data through the NSURLConnection? If not, is it possible you are hitting a TCP session timeout? Seems unlikely if the problem persists on a local server, but any intervening stateful firewall/packet inspector might be casting off your TCP connection.
Every so often, my iPhone app gets into a state where network requests always time out, even if other apps work fine (and can even access the same sites). This isn't obviously correlated with changes in network availability, and happens both on 3G and over WiFi. Any suggestions on how to diagnose the problem?
(FWIW, the app uses MonoTouch and HttpWebRequest, but I suspect whatever's going wrong is lower-level.)
Note: The problem persists through backgrounding the app and changing the network configuration; the only fix seems to be to kill the app and re-launch it.
Updates: I've tried making use of Reachability, but to no effect. Reachability.InternetConnectionStatus always returns ReachableViaWiFiNetwork (or ReachableViaCarrierDataNetwork, depending; likewise IsHostReachable() always returns true. Runtime.StartWWAN() seems to make no difference.
There was a bug open about this at https://bugzilla.novell.com/show_bug.cgi?id=555439 and there were several attempts at resolving it. As of the last comment in the bug, it was presumed fixed but I guess if you are using MonoTouch 4.0.3 then there some cases that are not worked around.
Basically, the problem is reflected in this other Stackoverflow question: iPhone 3G Connection Enabling
What MonoTouch does to try and work around this issue is to call MonoTouch.Runtime.StartWWAN(Uri) which opens a dummy connection to the uri using an NSUrlConnection to force-wake the network interface. Then, MonoTouch goes back to using the BSD socket API inside the HttpWebRequest.
Try setting the timeOutInterval property of the NSURLRequest used to make the call.
I have a app from where i hit different REST urls. one of the service is login service.
Now, do i have to use the apple rechability test everytime i want to make a connection?
I use ASIHttpRequest
No, ASIHTTPRequest will return a timeout error / a connection failure error if it can't reach the host. You can use those errors to show something to the user to tell them their login has failed.
The connectivity status of your mobile device can change very often and unforeseeably, so checking it often is advisable.
Say, for example, that you check at app startup, and find that not network is available. You go to offline mode, but then in a few minutes you could get in a WI-FI area or your 3G signal might be stronger. If you don't check it again, you lose the possibility of going to online mode.
Indeed, checking for network availability is pretty fast compared to how long a network request lasts (say: sending a login request and waiting for the response), so you can safely do the check whenever you need it according to your policy, be it at each request, every 5 minutes, or whatever.
EDIT:
about your concern as to the approval process: you should ensure that your app has a reasonable behavior when no connection it available. Simply showing an alert to the user (and not crashing) is enough for Apple, but you could also resort to disabling all your network related buttons, or whatever fits your app. The idea is that your app should not behave crazily when no connection is available.
If you want more advanced behavior, you can check reachability with each request.
You can also use the Reachability notification service (ASIHTTP-bundled Reachability includes that feature). You can find an how-to here. But in my opinion is a bit easier to just do the check when you need it. YMMV
From what I remember the reachability demo code is effectively a listener so can update a variable as the device's reachability state changes. You then need to check this variable before making a request.
Would be surprised ASIHTTP doesn't do this kind of thing already.
My application allows the user to download relatively large files (~120 MB) from my own dedicated server. I'm using the ASIHTTPRequest library for downloading.
It may sound weird, but everything worked fine until yesterday. I've tried downloading files countless times both from my app (on an iPad) and a Mac, and while on the Mac the download succeeds, on the iPad it randomly times out. Sometimes it goes until 100%, sometimes it reaches 30%-40% or something and then ASIHTTPRequest's downloadFailed: selector gets called. If I print out the error's localizedDescription, I get "The request timed out".
What could this mean? Could it be a problem of my app? Or a problem with my server, or my connection? I realize this could depend on several factors, so please ask me any information you need if necessary. Thanks.
I had weird network situations like timeouts on my ipad when using wifi that started after the upgrade to 4.2, but were intermittent.
Going to Settings -> General -> Reset Network settings and then reentering the wifi settings solved it for me.
(Also check that someone hasn't recently setup a new nearby wifi access point on the same channel as your network!)
Does your server have limit about the number of connections ? I encountered a problem because the number of connections are too much, then the server declines those connections. Then, they are time out.
Do you use WiFi or 3G connection? Non-WiFi connection allows to download files with maximum size of 20Mb only.
I have an iPhone app which communicates with a server to get the data being displayed. I have tested this app on a wifi connection and a good 3G connection. The app works without an issue. But if I test the app on a poor connection, the app crashes.
I get an XML from the server and parse it before displaying the data. I have put in the NSXMLParser method to show an alert if the parsing fails. The n/w connection code is also placed in try/catch blocks and we show an alert if the control goes to the catch block.
On a poor internet connection, the app just crashes (doesn't even go to the catch block) and checking the crash logs suggests the app could not get the complete response. Shouldn't it go to the catch block in that case? (I am using a wrapper class to make a synchronous connection)
This will always be an issue in any app using the internet if the connection is poor. Is there any way we can avoid this?
Thanks.
I am using the code provided here as the base for creating connections and getting the response
This isn't a direct answer, but may I suggest the ASIHTTPRequest library? I searched around for a long time looking for a good networking library and this seemed to be pretty bullet-proof through all sorts of connection issues.
It took me an afternoon to remove the lousy library I wrote and to integrate it. The other nice thing about it is that it can be done asynchronously.
It is available here: http://allseeing-i.com/ASIHTTPRequest/