Socket Server Programming

I'm currently writing a TCP/IP server for iOS devices in Swift. A connection is typically established in the following steps:


  1. Create a socket with the socket() system call
  2. Bind the socket to an address using the bind() system call. For a server socket on the Internet, an address consists of a port number on the host machine.
  3. Listen for connections with the listen() system call
  4. Accept a connection with the accept() system call. This call typically blocks until a client connects with the server.
  5. Send and receive data


The problem is step number 4. The server must always be listening for new connections, so the thread in which it runs is always blocked. How do I deal with this when the application enters in the background or the iDevice goes to sleep mode?

You've got several options, depending on just how attached you are to old fashioned BSD sockets:

  • Use multiple threads, and perform the accept() system call in something other than the main thread.
  • Use the non-blocking select() system call to poll for socket events, and only call accept() when an incoming connection occurs.
  • Use the CFNetworking API instead.


If you're going to insist on using the BSD socket API, you need to also be aware that it's more of a compatibility layer, and that important features (like informing the device that a network interface is in use, and shouldn't be shut down) are driven by the CFNetworking API and not by the BSD networking API.

How do I deal with this when the application enters in the background or the iDevice goes to sleep mode?

Well, you can put the

accept
call in a separate thread or use a GCD event source to run a non-blocking accept setup, but none of those will help you if the app gets suspended.

IMPORTANT I'm using the terms from Technote 2277 Networking and Multitasking here; you should read that before going further.

To successfully listen for incoming connections you have to prevent your app from being suspended. That's not a problem if your app is in the foreground. However, if it moves to the background—possibly because the user has screen locked the device—your app will typically become eligible for suspension and, if it gets suspended, there's no way to wake it up when a new connection arrives.

This gives you a number of options:

  • prevent suspension

  • don't listen when you might be suspended

  • rethink your overall approach

The last point is critical: iOS is not really meant to support third-party server processes, so things go a lot smoother if you can avoid this problem rather than tackling it head on.

Share and Enjoy

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

let myEmail = "eskimo" + "1" + "@apple.com"
Socket Server Programming
 
 
Q