14

I'm working on an iPhone application which will use long-polling to send event notifications from the server to the client over HTTP. After opening a connection on the server I'm sending small bits of JSON that represent events, as they occur. I am finding that -[NSURLConnectionDelegate connection:didReceiveData] is not being called until after I close the connection, regardless of the cache settings I use when creating the NSURLRequest. I've verified that the server end is working as expected - the first JSON event will be sent immediately, and subsequent events will be sent over the wire as they occur. Is there a way to use NSURLConnection to receive these events as they occur, or will I need to instead drop down to the CFSocket API?

I'm starting to work on integrating CocoaAsyncSocket, but would prefer to continue using NSURLConnection if possible as it fits much better with the rest of my REST/JSON-based web service structure.

Varun Kumar
  • 344
  • 2
  • 24
pix0r
  • 31,139
  • 18
  • 86
  • 102
  • Hey, I saw that you used asyncsocket to get the desired result. Any chance I could pick your brains about this sometime? I'm @suprfrends on twitter. It would be GREATLY appreciated! – Alec Sloman Apr 07 '11 at 04:57
  • I was able to figure this out .... check out: http://stackoverflow.com/questions/1293026/http-connection-with-nsurlconnection-in-iphone/14828690#14828690 – wakkus Feb 12 '13 at 08:53
  • I found a solution for it, see my reply here: http://stackoverflow.com/questions/1293026/http-connection-with-nsurlconnection-in-iphone/14828690#14828690 – wakkus Feb 12 '13 at 08:54
  • Here's a workaround that I found after a lot of pain :) http://stackoverflow.com/questions/1293026/http-connection-with-nsurlconnection-in-iphone/14828690#14828690 – wakkus Feb 12 '13 at 08:58

5 Answers5

7

NSURLConnection will buffer the data while it is downloading and give it all back to you in one chunk with the didReceiveData method. The NSURLConnection class can't tell the difference between network lag and an intentional split in the data.

You would either need to use a lower-level network API like CFSocket as you mention (you would have access to each byte as it comes in from the network interface, and could distinguish the two parts of your payload), or you could take a look at a library like CURL and see what types of output buffering/non-buffering there is there.

Matt Bridges
  • 48,277
  • 7
  • 47
  • 61
  • 1
    This is what I was afraid of. I think I'll go with CocoaAsyncSocket rather than deal with CFSocket myself. – pix0r Jul 13 '09 at 17:01
  • For the record, CocoaAsyncSocket ended up working great, though it took an extra hour or two to get everything working properly. – pix0r Jul 15 '09 at 17:36
  • 1
    The easiest fix is to make the response have text/json as content-type, see http://stackoverflow.com/a/14828690/371793 – mvds Apr 17 '13 at 23:14
  • For anyone hitting this thread while trying to listen to the CouchDB ```_changes``` feed: just send the accept header with ```Accept: application/json``` (```[request addValue:@"application/json" forHTTPHeaderField:@"Accept"]```) and you will get documents back as soon as they're posted to the stream. – Ell Neal May 23 '13 at 12:11
3

I ran into this today. I wrote my own class to handle this, which mimics the basic functionality of NSURLConnection.

http://github.com/nall/SZUtilities/blob/master/SZURLConnection.h

nall
  • 15,899
  • 4
  • 61
  • 65
0

It sounds as if you need to flush the socket on the server-side, although it's really difficult to say for sure. If you can't easily change the server to do that, then it may help to sniff the network connection to see when stuff is actually getting sent from the server.

You can use a tool like Wireshark to sniff your network.

Another option for seeing what's getting sent/received to/from the phone is described in the following article:

http://blog.jerodsanto.net/2009/06/sniff-your-iphones-network-traffic/

Good luck!

  • I can connect via telnet and verify that the data is coming down incrementally, as expected. It sounds like NSURLConnection always buffers the data as Matt mentioned. – pix0r Jul 13 '09 at 17:00
0

We're currently doing some R&D to port our StreamLink comet libraries to the iPhone.

I have found that in the emulator you will start to get didReceiveData callbacks once 1KB of data is received. So you can send a junk 1KB block to start getting callbacks. It seems that on the device, however, this doesn't happen. In safari (on device) you need to send 2KB, but using NSURLConnection I too am getting no callbacks. Looks like I may have to take the same approach.

I might also play with multipart-replace and some other more novel headers and mime types to see if it helps stimulate NSURLConnection.

  • I'd really recommend using CocoaAsyncSocket instead - it's simple enough to implement the basic HTTP commands yourself if you need them. Who knows how Apple might change NSURLConnection in the future... – pix0r Jul 22 '09 at 21:26
0

There is another HTTP API Implementation named ASIHttpRequest. It doesn't have the problem stated above and provides a complete toolkit for almost every HTTP feature, including File Uploads, Cookies, Authentication, ...

http://allseeing-i.com/ASIHTTPRequest/

Ali Nadalizadeh
  • 2,726
  • 3
  • 22
  • 24
  • And unlike rolling it yourself ASIHttpRequest seems to handle HTTP proxies, authentication, etc, all of which you lose if you decide "hey, it's just a socket connection plus sending a few headers, how hard can it be?" :)One of the main reasons to use COMET over TCP or UDP is that it goes through fascist corporate firewalls. – Matthew Phillips Oct 28 '10 at 06:00