tcp posix socket connect() failing with ECONNREFUSED on ios

Hi there. I'm developing a cross-platform app that makes use of posix sockets.


After the app has been running a brief while and created and closed a number of sockets I am no longer able to make any new connections. Creating a new socket and then attempting to connect() results in an error of ECONNREFUSED. (All sockets are blocking tcp, handled in separate threads)

I was concerned I might be leaking sockets. But all used sockets seem to be closed correctly, and there are no currently active sockets when the errors begin occurring.


This only seems to happen on iOS with iPhones (iPad's seem to be fine).

Are there any additional steps I need to be aware of when working with posix sockets on iOS?


Thanks

Are you connecting to a remote server? Or is this some sort of loopback thing?

ECONNREFUSED
is almost always the result of the remote server rejecting the connection. So, if you’re connecting to a remote server I recommend that you use a packet trace to look at the on-the-wire behaviour. That’ll allow you to distinguish between:
  • a correct connection that the server rejects — For example, the server might have rejected the connection because it’s busy because your client has not closed all the previous connections.

  • an incorrect connection — For example, you might have a bug that causes the client to use the wrong port number.

QA1176 Getting a Packet Trace describes how to get a packet trace on Apple platforms.

Are there any additional steps I need to be aware of when working with posix sockets on iOS?

There are lots:

  • BSD Sockets is not integrated with iOS’s connect-by-name subsystem, which causes problems for VPN On Demand, correct IPv{4,6} address selection, and so on.

  • BSD Sockets is not integrated with the reachability subsystem. This is particularly important on iOS, where the TCP/IP environment is highly dynamic.

    Note This one is easy to fix, as described in this post.

  • Implementing TLS on top of BSD Sockets is a pain.

Unless you have good reason to be using BSD Sockets (for example, you’re using a library whose code is shared with other platforms), I recommend that you use higher-level TCP APIs (NSStream, NSURLSessionStreamTask).

Even if you are using cross-platform code, it might make sense to use some sort of hybrid approach. For example:

  • You can use CFSocketStream for your initial connection and then extract the connected socket from the CFSocketStream and pass it to your cross-platform code which uses BSD Sockets. This allows you to integrate with connect-by-name.

  • A lot of network protocols implement a record layer built on top of TCP. In many cases replacing this record layer with an alternative implementation that transports data via one of iOS’s preferred APIs is not too onerous.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
tcp posix socket connect() failing with ECONNREFUSED on ios
 
 
Q