views:

270

answers:

1

I'm writing a Cocoa app. There is a socket in the application, and whenever the socket becomes readable I want to read data from the socket, process the data, and update the user interface accordingly. I want to integrate the read event check in the main loop, i.e. I want to attach the socket to the main loop and have the main loop call a callback whenever that socket becomes readable.

I've written a test application, but for some reason it doesn't work:

#include <stdio.h>
#include <Foundation/NSAutoReleasePool.h>
#include <Foundation/NSRunLoop.h>
#include <Foundation/NSPort.h>

@interface MyDelegate : NSObject <NSPortDelegate> {
}
- (void)handlePortMessage:(NSPortMessage *)portMessage;
@end

@implementation MyDelegate
- (void)handlePortMessage:(NSPortMessage *)portMessage {
    printf("Haiz\n");
}
@end

int
main() {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSSocketPort *server = [NSSocketPort alloc];
    MyDelegate *foo = [MyDelegate alloc];
    [server initWithTCPPort: 1234];
    [server setDelegate: foo];
    [[NSRunLoop mainRunLoop] addPort: server forMode: NSDefaultRunLoopMode];
    [[NSRunLoop mainRunLoop] run];
    [pool release];
    return 0;
}

The app is supposed to listen on localhost port 1234, and whenever someone connects to the server or sends data to the server, the app is supposed to print "Haiz" on the console. However the app does nothing at all. The socket is created and I can telnet to port 1234, but the app doesn't print anything to the console.

What am I doing wrong?

+1  A: 

From the documentation:

An NSSocketPort object can be used as an endpoint for distributed object connections.

That's not what you're doing here.

You want either NSFileHandle around a socket file descriptor from the BSD sockets API, or a CFSocket. This will let you put the socket on the run loop.

Peter Hosey
NSFileHandle is not an NSPort and there's no CFRunLoopSource for it so I cannot attach it to the main loop.
Hongli
I know NSFileHandle isn't an NSPort. NSPorts are for IPC. Your delegate method doesn't get called because you never receive a port message on that socket. As for attaching to the run loop, either send the file handle a `acceptConnectionInBackgroundAndNotify` message or use CFSocket instead.
Peter Hosey
I was under the impression that FoundationKit is just an objective C wrapper around CoreFoundation, but now it seems they're totally different and that there are some things that I can do with CoreFoundation but not with FoundationKit?The reason why I'm trying to cling to FoundationKit because I'm actually writing the app in MacRuby, not Objective C, and it has some problems with function pointers which the CoreFoundation APIs expect.
Hongli
Foundation is older than Core Foundation. Some Foundation classes are now wrappers for or toll-free-bridged with CF classes, but not all, and there are some things you can do with each that you can't do with the other.
Peter Hosey