NSFileHandleReadCompletionNotification and sockets
NSFileHandleReadCompletionNotification and sockets
- Subject: NSFileHandleReadCompletionNotification and sockets
- From: email@hidden
- Date: Fri, 14 Jun 2002 16:24:14 -0700
I have wrapped a socket up in an NSFileHandle so i can get async
notification that data has arrived on that socket from NSRunLoop...
It works very well, most of the time... I've included code below which
approximate my usage... (all error checking removed for clarity)
BUT, i'm finding in many cases, something the server side does causes
the runloop to call my dataFromServer method below with a ZERO length
NSData item... while the socket is still alive and well...
This is the equivalent of recv() returning -1, rather than 0...
It could be that the socket merely timing out and errno would have been
EAGAIN or EINTR...
oddly, errno is ENOENT when my callback is called... but that could be
unrelated to the recv().
Is there something that readInBackgroundAndNotifyForModes: is supposed
to do when the socket recv returns without data, but is still good?
static NSArray *sAllRunLoopModes;
+ initialize
{
sAllRunLoopModes = [[NSArray arrayWithObjects:
NSEventTrackingRunLoopMode,
NSModalPanelRunLoopMode,
NSDefaultRunLoopMode,
nil]
retain];
}
NSFileHandle *connectTo:(id)hostName port:(int)port
{
NSFileHandle *handle;
int socketfd = socket(AF_INET, SOCK_STREAM, 0);
struct hostent*remoteHost = gethostbyname([hostName cString]);
struct sockaddr_in remoteAddr;
bzero((char*)&remoteAddr, sizeof(remoteAddr));
remoteAddr.sin_family = AF_INET;
bcopy((char*)remoteHost->h_addr,
(char*)&remoteAddr.sin_addr.s_addr, remoteHost->h_length);
remoteAddr.sin_port = htons(port);
connect(socketfd, (struct sockaddr*)&remoteAddr, sizeof(remoteAddr));
handle = [[NSFileHandle alloc] initWithFileDescriptor:socketfd];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(dataFromServer:)
name:NSFileHandleReadCompletionNotification object:handle];
[handle readInBackgroundAndNotifyForModes:
[NSArray arrayWithObjects:NSEventTrackingRunLoopMode,
NSModalPanelRunLoopMode, NSDefaultRunLoopMode, nil]];
return handle;
}
- (void)dataFromServer:(id)notification
{
NSData *data = [[notification userInfo]
objectForKey:NSFileHandleNotificationDataItem];
int n = [data length];
if (n > 0) {
// ALL is well here, process the data, etc...
[[notification object] readInBackgroundAndNotifyForModes:
[NSArray arrayWithObjects:NSEventTrackingRunLoopMode,
NSModalPanelRunLoopMode, NSDefaultRunLoopMode, nil]];
} else {
// should only end up here if the server side of this
connection is actually GONE.
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter]
postNotificationName:ServerDied object:self userInfo:nil];
}
}
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.