Random latency between headers and body of POST - ios

We're using NSUrlConnection sendAsynchronousRequest to send simple POST requests to our Node JS server. Through analyzing tcpdumps, we've noticed that sometimes the request headers and request body are split into 2 separate TCP packets.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:url]];
[request setTimeoutInterval:3];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-type"];
[request setHTTPBody:postData];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler: ^(NSURLResponse *response, NSData *POSTReply, NSError *error) { }];
The problem is that occasionally the headers are sent to the server, which opens a connection to our API, and then multiple seconds later the body packet is sent. We're seeing a > 1 second delay between headers and body, randomly every hundred requests on the server side. It's the single largest source of latency on our API.
For the majority of requests, headers and body are about the same size (200 bytes each).
Has anyone seen this before?

I don't have concrete insights on the swift APIs (NSUrlConnection etc.) but in general, while the HTTP data is sent in chunks of large size (which can accommodate the 200 bytes in one packet), more granular decisions are taken at the underlying TCP level, which may decide to split these into chunks of lesser sizes.
I have observed this in node (sending side as well as receiving side) on specific platforms (such as AIX) where the packets are split at illogical boundaries by TCP. By TCP specification, applications should not rely on specific order or size of the low level data transport, it guarantees the data integrity at the final stage.
One suspect would be the presence of Nagile's algorithm in the TCP.
I would also recommend to change the client to another platform (such as Linux) and compare the behavior, if it is easy to port the code.
Hope this helps.

Related

HTTP request on 3G doesn't work

I try to send HTTP request from my Iphone to local server that run on my local network (behind a router).
I forwarded the port on my router as follow:
HTTP request is :
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://213.57.x.x:8080/OurDogsServerV2/DoggizzMain"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setAllowsCellularAccess:YES];
Over Wifi everything is working fine but I want to test 3G network (for end user).
I set a break point on doPost at my server (Apachi) so I don't think its time interval problem because I don't even get to my BP.
(I disabled my firewall).
I tried to change the url to http://213.57.x.x:8080/localhost:8080/OurDogsServerV2/ and some other combinations.
Can somebody suggest what else can I try?
It was totally my fault. In the options of my router I did disable the WAN Blocking but I didn't notice the apply button in the bottom (I think I assumed that apply button for port forwarding will include that option).

iOS - REST Client works fine while NSURLRequest returns NULL

I'm trying to download a file from a cloud via a GET HTTP request, and in my REST Client (Postman for Chrome) I get the results as expected, but when I pass the request in iOS, I get a NULL response. What could be the problem?
In my REST Client, I pass the URL as http://myserver.com/api/download.json?filepath=/&fileid=document:1pLNAbof_dbXGn43GtMNafABMAr_peTToh6wEkXlab7U&filename=My Info.doc with a header field for a authorization key, and it works perfectly fine.
While in iOS, if I do such a thing:
[request setURL:[NSURL URLWithString:URLString]]; // I tried even to hardcode the
// URLString to be one of the
// working URLs from the Postman
// Client, doesn't work as well.
[request setHTTPMethod:#"GET"];
NSData* response = [NSURLConnection sendSynchronousRequest:request
returningResponse:&urlResponseList
error:&requestErrorList];
response is null, and I get a status code 500.
Anyone know how to make this work? Thanks.
it looks like your URL has a space in it, you'll need to escape that before sending the string to NSURL.
it would also be helpful to know what the full error from your server is if this doesn't work. what does requestErrorList contain?
but if the only problem is the non-escaped characters something like this should work.
NSString *encodedString = [URLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[request setURL:[NSURL URLWithString:encodedString];
An HTTP status code 500 occurs when the webservice is not able to handle your request. An internal error occured.
Try to add some more details to your request.
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];

iOS app http post/get request

I need some tutorial, how to use HTTP POST (or GET) request from my iOS app. I want to send one string to my server and than write it to database. I've found this piece of code:
NSString *post = #"key1=val1";
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:#"http://www.nowhere.com/sendFormHere.php"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
I add it to UIAction button, but it don't send anything to my server. On my server, I have a PHP script that takes that "key1" from post and than it write it to db.
<?
$postr = $_POST["key1"];
$con0 = mysql_connect("server","db","pass");
mysql_select_db("table", $con0);
mysql_set_charset('utf8',$con0);
mysql_query("INSERT INTO tok (token) VALUES ('$postr')");
mysql_close();
?>
Can anybody tell me what I am doing wrong?
Look at AFnetworking and work through their api. Sending a post request using the api is very fast, and is what most apps use for web connectivity.
Also please dont be discouraged by sarcastic comments. You should tag iOS projects as iOS and not xcode (unless you actually need help with the actual program xcode). But I don't think it's productive to harrass everyone that comes in and makes this mistake. A more tactful way would be a personal message as opposed to a public retort
https://github.com/AFNetworking/AFNetworking
AFNetworking is a very powerful library that can help you to reduce the effort on create your HTTP requests, you can find several examples on how to use this library on its github page.
You may find this answer useful for your needs: AFNetworking Post Request

HTTP Post - Time Out - Multiple Request getting initiated within timeout interval

I am using HTTP Post method and initiating a synchronous request.
[NSURLConnection sendSynchronousRequest: ..]
For HTTP POST requests, the default time out is happening at 75 seconds as discussed in many threads.
But during that time out period of 75 seconds, Multiple web service requests are getting initiated for us for the same request raised with all the same parameters.
Please let us know What causes this multiple requests to get initiated? Is this due to HTTP POST in general or because of Synchronous request?
#iOS Sample Code
[body appendData:[[NSString stringWithFormat:#"\r\n--%#--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];
[request addValue:[NSString stringWithFormat:#"%d", body.length] forHTTPHeaderField: #"Content-Length"];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
NSURLResponse *response;
response = nil;
urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(urlData)
{
NSString *responseString = [[NSString alloc] initWithData:urlData encoding:NSASCIIStringEncoding];
[self parseStringInformation:responseString infoDict:informationDictionary];
//NSLog(#"%#",responseString);
}
Without the server's request-response logs there are several possibilities.
Programmer Error: Have you already gone through all of "gotchya" type situations?
Have you put a logging message right before your "urlData = [NSURLConnection sendSynchronousRequest: ..." line to make sure your code is only calling it once?
Are you calling this function from within your main GUI thread, if you are that's not supported/recommended, which means it could be causing side-effects like what you're describing. https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html
Are you sure your Request is set up as a POST and has the proper headers like "Content-type: multipart/form-data, boundary=X"
Web Server Responses: Without the web servers logs (or the code for the service your POSTing to) it's hard to say...
Perhaps your server is sending cyclical redirects to the client. If you don't implement a "connection:willSendRequest" then the redirects could be followed for ?X? amount of times for one request. http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/urlloadingsystem/Articles/RequestChanges.html
API Error: You've found some corner case which is causing unwanted side effects. Maybe apple has an bug tracker or developer support forum?
If this is the case you'll have to work around the bug, until it's fixed. I suggest implementing the Asynchronous call chain. "Loading Data Asynchronously" https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html

How to write data to the web server from iPhone application?

I am looking forward for posting some data and information on the web server through my iPhone application. I am not getting the way to post data to the web server from iPhone sdk.
It depends in what way you want to send data to the web server. If you want to just use the HTTP POST method, there are (at least) two options. You can use a synchronous or an asynchronous NSURLRequest. If you only want to post data and do not need to wait for a response from the server, I strongly recommend the asynchronous one, because it does not block the user interface. I.e. it runs "in the background" and the user can go on using (that is interacting with) your app. Asynchronous requests use delegation to tell the app that a request was sent, cancelled, completed, etc. You can also get the response via delegate methods if needed.
Here is an example for an asynchronous HTTP POST request:
// define your form fields here:
NSString *content = #"field1=42&field2=Hello";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://www.example.com/form.php"]];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:[content dataUsingEncoding:NSISOLatin1StringEncoding]];
// generates an autoreleased NSURLConnection
[NSURLConnection connectionWithRequest:request delegate:self];
Please refer to the NSURLConnection Class Reference for details on the delegate methods.
You can also send a synchronous request after generating the request:
[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
If you pass a NSURLResponse ** as returning response, you will find the server's response in the object that pointer points to. Keep in mind that the UI will block while the synchronous request is processed.

Resources