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.
Related
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
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'm developing a messaging app and I have to make a call to a server every x seconds to load from server the new messages.
I use a NSTimer that calls the server every x sec.
But for instance x = 1 sec and the response from server arrives after 1,5 sec. In this case I have one new request to the server that comes before that the previous request is satisfied, and this is a big problem for my app's logic. Can you help me to understand how can I check cyclically the messages on the server without have this problem?
Thank you.
Stop your timer before starting your web request, and then start it again when you get your answer.
You can send request to the server and once you have response (success/failure) send another one. In this scenario you will be sure that just one request is send and you can handle it easily.
I am working on websocket connection and I am using SocketRocket(https://github.com/square/SocketRocket) library for that, I am got successful in connecting with server, but connection gets disconnected at every few seconds. I dont know why this is happening as I want a persistent connection and Websockets are for that only
Help me if possible.
Thanks
I have a typical GKSessionModeServer/GKSessionModeClient setup.
When the server denies a client connection attempt with denyConnectionFromPeer:, the client's session:connectionWithPeerFailed: method is called, but then it receives a GKPeerStateConnected state change with my server's peerID. In other words the client thinks the connection succeeded while the server does not.
This seems to be at odds with common sense and the documentation for connectToPeer:withTimeout:, which says
If the connection to the remote peer is successful, the delegate’ session:peer:didChangeState: method is called for each peer it successfully connected to. If the connection fails or your application cancels the connection attempt, the session calls the delegate’s session:connectionWithPeerFailed:withError: method.
I know this doesn't say that the state change callback won't be called in the case of a connection failure, but the net result from the client's point of view is that a failed connection appears to result in a successful connection.
Clutching at straws I tried calling cancelConnectToPeer from the connectionWithPeerFailed callback, without result.
The client could work around this by ignoring the next GKPeerStateConnected, but this is kludgey and complicates reconnecting when the server starts accepting connections again.
So why can't the client session understand that it's over?
I have designed the same kind of application myself (GKSessionModeServer/GKSessionModeClient).
When you refuse the connection to a peer, it will trigger the session:peer:didChangeState: delegate, with the GKPeerConnectionState argument set to GKPeerStateDisconnected.
You just need to handle this properly in your code - I've never had any issue with that part whatsoever.