Skip navigation.
 
mlRe: Implementing a TCP port listener in Cocoa
FROM : Jakob Olesen
DATE : Wed Jun 28 21:16:32 2006

On 28/06/2006, at 16.06, Rick Hoge wrote:

>
> I would like to implement an internet service from within a Cocoa 
> application such that when a remote client requests a connection on 
> a certain port the connection and subsequent service will be 
> handled by the Cocoa application.
>
> I want to do this using Cocoa Foundation classes if possible, but 
> it's not really clear from the documentation how to set this up. 
> Most of the documentation is geared towards Distributed Objects 
> (DO) and not provision of a TCP port service in the classic Unix 
> sense.


I think you need to use Core Foundation for a listening socket. 
CFSocket lets you create a socket that listens for incoming 
connections in a run loop. You get a callback for each connection. 
Check out http://developer.apple.com/samplecode/CFLocalServer/
index.html It is for UNIX domain sockets, but you can do the same for 
INET sockets.

Once you get a connection, you are passed a bsd-style file descriptor 
in the accept callback. Pass that to CFStreamCreatePairWithSocket() 
to get a CFReadStreamRef+CFWriteStreamRef pair. These are toll-free 
bridged to NSInputStream and NSOutputStream.


The code below is a bit messy - it is part of a Ruby wrapper for 
CFSocket. Apple's sample code is probably better.

static void
accept_callback(CFSocketRef s, CFSocketCallBackType callbackType, 
CFDataRef address, const void *data, void *info)
{
    if (callbackType!=kCFSocketAcceptCallBack)
        return;
    CFSocketNativeHandle fd = *(CFSocketNativeHandle*)data;
    // pass fd to CFStreamCreatePairWithSocket...
}

// ServerSocket.new(:host, port)
static VALUE
socket_initialize(int argc, VALUE *argv, VALUE slf)
{
    VALUE ahost, aport;
    rb_scan_args(argc, argv, "02", &ahost, &aport);

    Socket *s = DATA_PTR(slf);
    struct addrinfo hint;
    memset(&hint, 0, sizeof(hint));
    hint.ai_family = PF_UNSPEC;
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_protocol = IPPROTO_TCP;
    hint.ai_flags = AI_PASSIVE | AI_CANONNAME;
    const char *hostname = NIL_P(ahost) ? 0 : StringValuePtr(ahost);
    const char *servname = NIL_P(aport) ? 0 : RSTRING
(rb_obj_as_string(aport))->ptr;
    struct addrinfo *res = 0;
    if (getaddrinfo(hostname, servname, &hint, &res))
        rb_sys_fail("getaddrinfo");
    if (!res)
        rb_raise(rb_eIOError, "getaddrinfo(%s,%s) failed", hostname, 
servname);

    CFSocketContext ctx = { 0, (void*)slf, cf_ruby_retain, 
cf_ruby_release, cf_ruby_copy_description };
    s->sock = CFSocketCreate(kCFAllocatorDefault, res->ai_family, 
res->ai_socktype, res->ai_protocol, kCFSocketAcceptCallBack, 
accept_callback, &ctx);
    if (!s->sock) {
        freeaddrinfo(res);
        rb_sys_fail("couldn't create socket");
    }

    CFDataRef addr = CFDataCreate(kCFAllocatorDefault, (UInt8*)res-
>ai_addr, res->ai_addrlen);

    //NSLog(@"getaddrinfo(%s,%s) -> %s %@", hostname, servname, res-
>ai_canonname, addr);

    freeaddrinfo(res);

    int yes = 1;
    setsockopt(CFSocketGetNative(s->sock), SOL_SOCKET, SO_REUSEADDR, 
(void *)&yes, sizeof(yes));

    // now bind
    CFSocketError err = CFSocketSetAddress(s->sock, addr);
    CFRelease(addr);
    if (err!=kCFSocketSuccess) {
        rb_sys_fail("couldn't bind socket");
    }
    return slf;
}

static VALUE
m_accept(VALUE slf)
{
//    NSLog(@"accept slf=%p", slf);
    Socket *s = DATA_PTR(slf);
    s->block = rb_block_proc();
    CFRunLoopSourceRef rls = CFSocketCreateRunLoopSource
(kCFAllocatorDefault, s->sock, 0);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, 
kCFRunLoopCommonModes);
    CFRelease(rls);
    return Qnil;
}

Related mailsAuthorDate
mlImplementing a TCP port listener in Cocoa Rick Hoge Jun 28, 16:06
mlRe: Implementing a TCP port listener in Cocoa Jakob Olesen Jun 28, 21:16
mlRe: Implementing a TCP port listener in Cocoa Andrew Bowman Jun 28, 23:35
mlRe: Implementing a TCP port listener in Cocoa Jakob Olesen Jun 28, 23:58
mlRe: Implementing a TCP port listener in Cocoa Douglas Davidson Jun 29, 00:00
mlRe: Implementing a TCP port listener in Cocoa Andrew Bowman Jun 29, 00:30
mlRe: Implementing a TCP port listener in Cocoa Douglas Davidson Jun 29, 00:39
mlRe: Implementing a TCP port listener in Cocoa Rick Hoge Jun 29, 03:00
mlRe: Implementing a TCP port listener in Cocoa Dustin Voss Jun 29, 03:35
mlRe: Implementing a TCP port listener in Cocoa glenn andreas Jun 29, 05:11
mlRe: Implementing a TCP port listener in Cocoa Rick Hoge Jun 29, 05:34
mlRe: Implementing a TCP port listener in Cocoa Jakob Olesen Jun 29, 11:40
mlRe: Implementing a TCP port listener in Cocoa Rick Hoge Jun 29, 14:44
mlRe: Implementing a TCP port listener in Cocoa Greg Herlihy Jun 30, 07:52