Would anyone know what are the timeouts configuration for [NSURLSession sharedSession]?
I am doing some debugging and this information would be very helpful.
Edit
Apparently my question is not clear (!). I am not asking how to change the timeout. I am asking what the default is. So this is not a duplicate.
There are two timeouts for URL sessions. The first is the maximum time allowed between receiving new data. This is called the timeoutIntervalForRequest. The second is the maximum time the entire request is allowed to take (assuming it's regularly receiving new data). This is called the timeoutIntervalForResource.
Both of these timeouts are configured by default using NSURLSessionConfiguration, and can be overridden on the NSURLRequest.
The default timeoutIntervalForRequest is 60 seconds.
The default timeoutIntervalForResource is 7 days.
There are three timeout URL sessions now. Following are the details:
timeoutInterval - The connection timeout is the timeout in making the initial connection i.e. completing the TCP connection handshake.
If during a connection attempt the request remains idle for longer than the timeout interval, the request is considered to have timed out.
The default timeout interval is 60 seconds.
timeoutIntervalForRequest - The timeout interval to use when waiting for additional data to arrive before giving up. This value is reset once new data arrive. The default value is 60.
timeoutIntervalForResource - Any upload or download tasks created by a background session are automatically retried if the original request fails due to a timeout. To configure how long an upload or download task should be allowed to be retried or transferred, use the timeoutIntervalForResource property. The default value is 7 days.
Refer apple documentation for more details: timeoutInterval, timeoutIntervalForRequest and timeoutIntervalForResource
Related
I'm experiencing slow response times for my first http POST request to my server.
This happens both in Android and iOS networking libraries. (Volley on Android, and Alamofire in iOS).
First response is roughly 0.7s-0.9s, whereas subsequent requests are 0.2s.
I'm guessing this is due to the session being kept-alive by the server, therefore eliminating the need for establishing a new session on each request.
I figure I can make a dummy request when the app starts to start the session, but it doesn't seem very elegant.
I also control the server side (Node.js) so if any configuration needs to be done there I can also try it.
Investigating a little further, I tried sending an https CONNECT request before issuing the first "real" POST request, and the behavior replicates.
After 30 seconds or so, the connection is dropped (probably at the iOS URLSession level, the load balancer is configured to keep connections as 60 seconds).
In theory this makes sense because setting up an https connection takes up several (12 total) packets and I'm on an inter continental connection.
So my solution is to send a CONNECT request when I expect the user to send a regular request.
I have an app that lets the user send messages with images. A user might hit send, then immediately close their phone or switch to another app.
We were running into an issue that if there's temporarily a bad network connection the message would fail to send. We switched to using NSURLSession backgroundConfigurationWithIdentifier so that backgrounding the app doesn't immediately time out the running request. We switched to using this for all our api requests, thinking that it wouldn't hurt for every request to able to continue in the background if the app were closed at the wrong time.
Fast forward a couple weeks we're noticing all requests seem slow. Using wireshark I just discovered that this background session seems to use a new http connection per request, meaning it requires setting up a TCP connection and new TLS handshake for every request, which was adding a ~500ms latency on every request in our app. This is a pretty big deal but I can't find this behavior documented anywhere, including the link above or Apple's background transfer considerations.
So my question is, is this behavior expected, or am I doing something wrong somewhere? Is there an easy way with NSURLSession to make an HTTP request that will use an existing keep-alive connection if there is one, but can fall back to the backgroundConfiguration if the app gets moved to the background?
NSURLSession is the recommended way to fulfill your use case. Have you tried setting backgroundSessionConfig.discretionary = true
iOS Reference
A Boolean value that determines whether background tasks can be
scheduled at the discretion of the system for optimal performance.
If that doesn't help, I recommend filing a bug with iOS.
My main question is how to detect the application termination by the end user when it was in the background (Suspended) to be able to send logout request to the server ?
We already have a timeout interval in the server to kill the session, but assume that the interval is 5 minutes so this means that the session will be alive for 5 minutes after the user terminated the app and anyone can sniff on the data and reuse it.
Notes:
We use HTTPS connection and SSL Certificate Pining.
We also implemented a heartbeat web service to be called by client app every fixed interval to tell the server to keep the session alive for this interval, if this web service didn't call for specific session, the server will kill this session.
Once your app is suspended you don't get any further notice before you are terminated. There is no way to do what you want.
Plus, the user could suspend your app to do something else (like play a game) and then not go back to your app for DAYS.
If you want to log out when the user leaves your app, do it on the willBeSuspended message. Ask for more background time and send a logout right then and there.
Mohamed Amer,
Here is an approach used by Quickblox Server and I feel its pretty much solid though it involves a little overhead.
Once the client application (either iOS android) establishes the session with quickblox server, quickblox server expects the client application to send the presence information to server after a regular interval continuously.
Sending the presense information is pretty much simple. They have written a api which we keep hitting after a interval of 5 mins with session id that we have. They validate the session id and once found valid they will extend the expiration time for the user ascociated with that id for 5 mins more.
What they will do I believe is that,
Approach 1 : they maintain the last hit time and for all the subsequesnt request they check if the request time is within the the time frame of 5 min if yes simply process it. If the request comes after 5 min they will delete the session id for the user and respond saying you have timeout the session.
Approach 2 : Because they provide online and offline info as well they cant simply depend on the incoming request to delete the session id from server so they probably create a background thread which swipes over the db to find the entry with last hit time greater then 5 min and removes it from DB. and declares the user session expired.
Though this involves client apps continously hitting the server and increases the burden on the server for the app like chat application in which presense information is so vital this overhead is still fine i believe.
Hope I have provided you with some idea at least :)
When I set up NSURLSession/Alamofire.Manager with a background session configuration, if there is no internet connection, I'm expecting to receive the usual NSError "Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline.".
This happened regularly if I'm not using a background configuration, but if I do such configuration my callback/delegate method will never be called. It will eventually be called when I activate the wifi again.
I'd prefer to receive an error straight away. Am I missing something?
The reason that why the network failure in background session task does not return any error is:
In general an NSURLSession background session does not fail a task if
something goes wrong on the wire. Rather, it continues looking for a
good time to run the request and retries at that time. This continues
until the resource timeout expires (that is, the value in the
timeoutIntervalForResource property in the NSURLSessionConfiguration
object you use to create the session). The current default for that
value is one week!
I found the above answer at developer forum.
More details which might help in the background session:
Another benefit is that in a background session, we monitor the
network and power environment for you. This means that we cover things
like network reachability and connectivity for you, so you don't have
to use the reachability APIs at all. We won't attempt to establish a
connection until we know that the server is reachable. And similarly,
if the user is performing a download and steps out of Wi-Fi, normally
that task would then fail with a transmission error. But, in a
background session, we'll actually recover from that automatically and
retry it and resume where we left off if the download is resumable.
And you won't hear about that error.
Source: WWDC 2014
The API doesn't tell you that the network is not present, because that would be an error, indicating that the connection will never finish. In reality, it will, assuming the network eventually comes back.
If you need to receive the error for some reason, don't use a background session.
Alternatively, if you just want to know whether the network is up or not for some sort of UI hint, use the reachability API. With that said, don't refuse to start the request based on failed reachability, because reachability lies.
I know there is a setTimeoutInterval method to NSMutableURLRequest, but can i set a specific timeout to the time it takes to reach and connect to the server?
No, you can't. Timeout is the time by which we expect the reply from server. We have no idea what time had gone to connect to server and what time for the server to reply.
A NSURLConnection will abort the connection with a timeout error if the connection is "idle" for longer than the specified duration set via setTimeoutInterval.
That means, if you start a request and the client did not receive anything from the server so far, you should get a timeout error in connection:didFailWithError: after that duration.
That also means, if you are in the middle of a connection sending/receiving data, and the server later hangs and the connection becomes "idle" for longer than the specified timeout, it will also abort the connection.
Whenever the connection has some progress, the timer will be reset.
You can tweak that behavior in so far that you start your own timer which sends cancel to the connection after a specific duration. Possibly you may monitor the progress and estimate how long the request will take to finish and then possibly invoke the cancel if that will take to long.