tcpnsstreamnsinputstreamnsoutputstreamcfstream

How to create a NSInputStream/NSOutputStream pair by accepting a server socket?


I know that you can create a NSInputStream and NSOutputStream pair (toll-free bridged to CFReadStream, CFWriteStream) by opening a TCP client connection using CFStreamCreatePairWithSocketToHost according to the Stream Programming Guide.

How can one create a TCP server that listens on a port and accepts a connection as a NSInputStream and NSOutputStream pair?


Solution

  • The RemoteCurrency sample project provides an example of this in QServer.m (previously known as TCPServer.m). The sample code is actually for setting up Bonjour advertising, but that part can be excluded for a simple TCP server.

    You create a socket with your own accept callback by calling CFSocketCreate, bind and listen to a port by calling CFSocketSetAddress, and start getting accept callbacks by calling CFSocketCreateRunLoopSource followed by CFRunLoopAddSource.

    Then, in the accept callback, you create NSInputStream/NSOutputStream pair from the connection handle using CFStreamCreatePairWithSocket, set the input stream’s delegate and start receiving recv callbacks by calling scheduleInRunLoop:forMode:, and then open both streams to start using them.

    Using NSInputStream and NSOutputStream abstractions (as opposed to creating a new thread and calling the standard UNIX functions socket, bind, listen, accept, send, recv) allows one to easily receive network events in the same NSRunLoop as the rest of the run-loop based APIs on OSX.