Here is my connection code:
- (void)sendData: (NSString*)someData {
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:nsURL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:180.0];
[theRequest setHTTPMethod:#"POST"];
[theRequest setTimeoutInterval:180.0];
[theRequest setHTTPBody:[sdata dataUsingEncoding:NSASCIIStringEncoding]];
NSError *error= nil;
NSData *result = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
}
I am calling this method whenever I have to send some request to the user. However, I want to maintain a specific connection session, and send requests, without creating the connection again and again. (as, the URL is a secure connection, and everytime it creates a connection, it wastes a lot of time).
How can I do this? Is there any way of creating a global object for connection in this class(where sendData method is written), so that for the lifetime of that object, there is only one connection.?
Cellular provider restrictions aside, the choice to keep a connection open is up to the server, not the client. If this is a request over HTTPS, you want to look at your server documentation regarding keep-alive connections and increase the timeout to a value that makes sense for your app.
The URL loading system will automatically re-use a connection to the same server, provided that it has not been closed by the server.
Note that increasing the keep-alive timeout on your server to a large value will mean a potentially significant increase of the resources used by the server.
Related
As soon as, I send request to the server (via NSURLConnection sendSynchronousRequest method), the server receives it in about 2 seconds, it processes and sends back response in another 3-5 seconds. However, I only get back the response in 30-35 seconds. This delay makes our communication very slow.
Even the async APIs are getting a delayed response.
Earlier, everything was working fine, with client getting the response back within 10 seconds.
Anyone else having this issue? What could be the reason?
EDIT
here is a screenshot of Wireshark analysis:
Link to a better image
How should I see what packet is saying what?..and why is it getting delayed?
EDIT2
Here is the code:
NSHTTPURLResponse *response=nil;
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:nsURL] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:180.0];
[theRequest setHTTPMethod:#"POST"];
[theRequest setTimeoutInterval:180.0];
[theRequest setHTTPBody:[[NSString stringWithFormat:#"%#",sdata] dataUsingEncoding:NSASCIIStringEncoding]];
NSError *error= nil;
NSData *result = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
if (error ) {
NSLog(#"error sending synchronous request: %#", error);
}
NSLog(#"request completed with code:%d",response.statusCode);
I'd avoid calling sendSynchronousRequest. Use the asynchronous version instead if you're not doing the call already on a background thread (you don't want to block the UI thread).
How do you know when the iOS response is received? An NSLog? A UI state change?
See also these questions:
NSURLConnection sendSynchronousRequest - background to foreground
NSURLConnection sendSynchronousRequest taking too much time to respond
Update
If you're a bit stuck, one strategy might be to rule out the use of NSURLConnection as the problem.
Strategy 1: try using NSURL's asychronous connection call instead of synchronous
Strategy 2: try using a different HTTP lib, such as AFNetworking
If you want to take a closer look at what is going on with the HTTP connection, you can use tools such as Charles, Fiddler or Wireshark to debug what data is being sent and received. To get the most benefit from this sort of analysis, you need to have some knowledge of the HTTP protocol(s). This is probably more time consuming than the previously mentioned strategies.
See also questions such as How to monitor network calls made from iOS Simulator.
Update
Are you accessing a webserver of your own, or is it someone else's?
Have you had a close look at the headers being sent to your webserver (and the ones being returned)? Pay attention to the content length, for example. Wrong content length can cause a delay, as explained here.
To see the request and returned headers, you could use Firebug, or something like wget or curl on the command line.
Also, double check that there's not a newline on the end of your URL, as described here.
Solution that worked for me:
In the request headers, iOS sets "gzip" for "Accept-Encoding" by default. The gzip compression was taking a lot of time, and hence the delayed response. I did the following to solve the problem:
[theRequest setValue:#"" forHTTPHeaderField:#"Accept-Encoding"];
NOTE: Check your headers, for any response delay.
Thanks to #occulus for directing me to the request headers!
You do this over wifi or celluar?
Speaking from my experience, when my data useage is exeeded my phone-provider slows down my downloads. Sometimes this happen to me at the end of the month after I did use a lot of mobile data.
I am not sure to say but it may be network problem first check it. it proper or down ?? okay Maybe I will be wrong.. but first check it...
Following describe code it might solve your problem :)
NSString *url = #"Your URL ";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0];
[request setHTTPMethod:#"POST"];
NSMutableData *body = [NSMutableData data];
.
.
/// Add Here Your NSMutableData Valuew
.
.
[request setHTTPBody:body];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (theConnection)
{
self.responseData = [[NSMutableData alloc] init];
}
else
NSLog(#"Connection Failed!");
To ease your problems with asynchronous HTTP Request you should consider using the AFNetworking framework
I'm creating an iPhone app that consumes a json webservice. I have an NSURLRequest and NSURLConnection object that are used to load JSON data from that webservice:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
initWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:30];
[request setHTTPMethod: #"POST"];
//[request setHTTPShouldHandleCookies:YES];
//create connection
NSURLConnection *connection = [[NSURLConnection alloc]
initWithRequest:request delegate:self];
[connection start];
First time I executed the above code, using as the url "admin.mydomain.com/param1/value1/param2/value2", the response came through correctly (a JSON string: {"Wrong API Key"}).
I then changed the url to my staging server: "admin.stg.mydomain.com/param1/value1/param2/value2". This server provides me with some completely different output (when I try that new url in a browser, the correct output is shown, a json object completely different from what the first url gives me), but in my iphone app I still get the exact same response I got from the other server. If I try non existent urls I do get a correct error message.
It just seems to have cached the result from the original server and returns the same value for my stg subdomain, somehow matching the two urls (is this possible?), but I have cleared all caching data I could find. I have tried to clean the build and build directory, restarted xcode, the computer and everything, the cache policy is set to ignore the cache (see code). Important: I get the same behavior on my actual iPhone, not just the simulator.
Does anyone have any idea what could cause this kind of behavior? Am I forgetting something obvious?
I have been looking at this for hours on end now, any help is greatly appreciated!
I have changed the request method to 'GET', now I get the expected results! When checking the url in the browser a get request is used, when posting it I get a different response, which happens to be exactly the same as what I get on the dev server. Problem solved, just have to make some adjustments to the backend to allow a post request!
I have two questions.
I have my data in XML format on web server. How can i connect it and use that data.
Is this secure? Can i use it in professional application?
Thanks for any sort of advice in advance.
To get xml file from url:
NSMutableString *serverURL = *xml url here*;
NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:[NSURL URLWithString:serverURL]];
[request setHTTPMethod:#"GET"];
NSData *responsedata = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
Is it secure? It depends on how secure you need. If you're just transferring generic data, it doesn't really need to be secure. If you're transferring sensitive or personal data, then you need to (at minimum) use a secure SSL connection and some sort of authentication scheme.
I am writing an app that’s a very simple web service client.
I have the following questions:
1. Is there a standard common way to write the web service consumption part so that it won’t interfere with the main GUI thread? Is it common practice to use the main thread considering the web request should take a very short time to complete (but never know)?
Any links to tutorials?
2. All examples I saw call the web service via GET. I need to POST the data to the web service.
Any known samples/tutorials that use POST?
If you're using the iPhone's built-in web request API, NSURLConnection, you run the request on the main thread but you run it asynchronously, with callbacks to a delegate as data is returned. This leaves the application responsive to user events. If the parsing or processing of the returned data takes too long to run on the main thread then you should run the NSURLConnection on the main thread, then hand off response data either incrementally or after the download is complete to a secondary thread for pure compute processing.
It is possible to start NSURLConnections on a non-main thread but you'll need to create a runloop on the non-main thread, and there are reports of random thread-safety bugs in the Apple libraries. If you really need to run the request itself on a non-main thread you can use the third party library ASIHTTPRequest, but you shouldn't need to do this except in very specialized circumstances.
Generating a POST request is straightforward with NSURLConnection:
NSString * requestBody = #"format up your body here, which is often form-urlencoded";
NSURL * nsurl = [NSURL URLWithString: #"http://example.com/post_request_receiver"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:nsurl];
// set appropriate content type here, usually application/x-www-form-urlencoded
[theRequest addValue: #"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[theRequest addValue: [NSString stringWithFormat:#"%d", [requestBody length]] forHTTPHeaderField:#"Content-Length"];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody: [requestBody dataUsingEncoding:NSUTF8StringEncoding]];
conn = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];
I am creating my first iPad app. I have a web application that I would like to authenticate against and pull data from in a RESTful way.
If you open up the URL in the browser (https://myapp.com/auth/login), you will get a form to enter your username and password. I was thinking I could set the login credentials in the post data of the request and submit the data.
The site uses HTTPS for login so that credentials aren't passed in plain text over the internet.
How can I make a secure HTTPS connection to pass credentials? Will this remember that I am logged in for future requests? What is the best way to do this?
Further update, October 2013
Although at the time I wrote this answer, ASIHTTPRequest was maintained a widely supported, this is no longer the case. It is not recommended for new projects - instead use NSURLConnection directly, or use AFNetworking.
With AFNetworking, there is a [httpClient setAuthorizationHeaderWithUsername:username password:password]; method for http authentication, and create a POST style form is equally easy - see AFNetworking Post Request for that.
Original answer:
A lot of people use the ASIHTTPRequest class to deal with http & https on the iPhone/iPad, as it has a lot of useful features that are difficult or time consuming to achieve with the built in classes:
http://allseeing-i.com/ASIHTTPRequest/
Starting at the simplest level you'd start with something like:
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
NSString *response = [request responseString];
NSLog(#"response = %#", response);
}
If you're using HTTP authentication, ASIHTTPRequest will automatically prompt the user for the username and password.
IF you're using some other form of authentication you probably need to request the username and password from the user yourself, and submit them as a POST value or a custom http header, and then the response may either include a token in a JSON or XML response, or it could set a cookie.
If you add more details as to how the authentication scheme works I can be a bit more specific.
Update
Based on the update, to emulate a POST form you'd just need to add lines like:
[request addPostValue:usernameString forKey:#"username"];
[request addPostValue:passwordString forKey:#"password"];
You will also need to change the way you create the request, instead of:
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
do:
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
(I also forget to mention it above, there's code I put earlier is using a synchronous request, so you'd want to replace it with an asynchronous one to avoid blocking the UI once you'd proved it was working.)
There's a JSON framework for the iphone here:
http://code.google.com/p/json-framework/
which works well for me and is simple to use with ASIHTTPRequest.