Subscribe to
NSLog(); Header Image

NSURLConnection Issues

From the Cocoa-Dev mailing list. Can you help?

I'm writing an app that uses NSURLConnection for getting some files (using the delegate callbacks), and sometimes, that connection just sits there and does nothing, even though the timeout should have killed it a while ago (the server is working properly). I tried to create a workaround by using an NSTimer that kicks in right after the timeout should have killed the connection, sends the -cancel message to the connection if it's still there without having received any data and quits the thread. That works fine in the UI, since I can tell when it has timed out (which is bad anyways, since it shouldn't time out when the server is working properly).

However, the NSURLConnection is not released (even though the thread itself has already terminated and the retain/releases are properly balanced), and the file descriptor is kept open. Fetching is occurring periodically, so after a while the per-process limit of open file descriptors is reached (256 I think), and the process quits silently (since NSAlert can't even put up an alert box, since the nib-file can't be loaded).

Has anybody an idea how to fix that problem? (I'm particularly interested in solutions for the initial problem, not the one that's caused by the workaround)

I've seen this one first-hand and haven't found the solution yet. Anyone got any info? I'll give prizes to those who help. 🙂

5 Responses to "NSURLConnection Issues"

  1. Rather than work with NSURLConnection, what I've done is just use curl and libcurl (See the webpage for cURL) to do any downloading. It's generally quicker, requires less memory overhead and doesn't have the issues that NSURLConnection (and the underlying CFHTTPRequest) have.

    If you can get away with using the "easy" interface for libcurl, changing your code to use it should be trivial. Doing all transfers serially on a separate thread should be the quickest way to get set-up. See this page for a really barebones example of how to use it.

    Good luck

  2. Doug, that's not a solution. The help is appreciated, but your answer is akin to "Doc, it hurts when I push here. So don't push there." It doesn't help to solve outstanding issues in core, key frameworks used by hundreds or thousands of other applications.

  3. Could it be a result of slow DNS servers, like the problem with Safari when a page won't load on first request, but it you click in the address bar and hit Enter again, it loads fine? Just a thought....I could be terribly wrong.

  4. One reason I always try to stick with NSURLConnection is to get all the system proxy configuration for free.

  5. The problem is that NSURLConnection tries to be "better" than is really necessary. If the remote server supports HTTP 1.1 it will try to use the HTTP 1.1 keep-alive feature, keeping the connection alive for as long as possible, just in case you may want to get something from that server again (in which case it could just re-use the already existing connection without having to establish a new one first). HTTP 1.0 has no keep-alive support, thus for servers running that version, it will really close the connection immediately after each GET. To make sure the connection really is kept open as long as possible it must further regularly push some keep alive traffic over it, otherwise server thinks the connection has been idle for too long and closes it.

    Apple has already pointed out, that there is no way to force NSURLConnection to not use the keep alive feature. It is possible to manually set HTTP header values in a NSURLRequest object, but not for the Connection field (you can set it to "close", but when you perform the request, you'll see that it is sent as "keep-alive"). According to Apple you shall use CFSockets when you want absolute control over the connection establishment and termination and do the HTTP call yourself.

    Well, CFSocket is part of the core libraries... but before I emulate NSURLConnection on top of CFSocket I rather go with Doug's suggestion and use some other library (which will also give me HTTPS support, that I had to implement myself otherwise).