From 05a11cf00200aaaa11bcde9c0efa2bc88b14b57e Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Thu, 2 Aug 2007 21:57:16 -0700 Subject: [PATCH] Starting to thread-ify SocketWrapper class. * Source/SocketWrapper.h: Defined connect: and _port, and internal method block * Source/SocketWraper.m: ([SocketWrapper connect]): New method. Dispatches thread to _connect ([SocketWrapper _connect:]): Threaded method that does the actual connecting to the socket ([SocketWrapper initWithPort:]): Removing connection stuff and placing it in an explicit commit method ([SocketWrapper _postNotification:withObject:]): New helper method. * Source/DebuggerConnection.m: ([DebuggerConnection socketAccepted]): New method ([DebuggerConnection initWithPort:]): Call [socket connect] and don't release it in the method any more --- Source/DebuggerConnection.m | 19 +++--- Source/SocketWrapper.h | 6 ++ Source/SocketWrapper.m | 121 ++++++++++++++++++++++-------------- 3 files changed, 90 insertions(+), 56 deletions(-) diff --git a/Source/DebuggerConnection.m b/Source/DebuggerConnection.m index a155add..89c1a60 100644 --- a/Source/DebuggerConnection.m +++ b/Source/DebuggerConnection.m @@ -35,16 +35,8 @@ // now that we have our host information, open the socket _socket = [[SocketWrapper alloc] initWithPort: port]; - if (_socket == nil) - { - // TODO - kill us somehow - NSLog(@"can't proceed further... SocketWrapper is nil"); - } - [_socket setDelegate: self]; - [_socket receive]; - - [_socket release]; + [_socket connect]; // clean up after ourselves [[NSNotificationCenter defaultCenter] addObserver: self @@ -107,4 +99,13 @@ NSLog(@"data sent"); } +/** + * Called by SocketWrapper after the connection is successful. This immediately calls + * -[SocketWrapper receive] to clear the way for communication + */ +- (void)socketAccepted +{ + [_socket receive]; +} + @end diff --git a/Source/SocketWrapper.h b/Source/SocketWrapper.h index 2b10f7c..b2dba33 100644 --- a/Source/SocketWrapper.h +++ b/Source/SocketWrapper.h @@ -18,7 +18,9 @@ @interface SocketWrapper : NSObject { + int _port; int _socket; + id _delegate; } @@ -27,6 +29,7 @@ - (id)delegate; - (void)setDelegate: (id)delegate; +- (void)connect; - (void)receive; - (void)send: (NSString *)data; @@ -45,4 +48,7 @@ - (void)dataReceived: (NSString *)response; - (void)dataSent; +// ============== internal functions for threading +- (void)_connect: (id)obj; + @end diff --git a/Source/SocketWrapper.m b/Source/SocketWrapper.m index aeec5d0..d159586 100644 --- a/Source/SocketWrapper.m +++ b/Source/SocketWrapper.m @@ -30,53 +30,7 @@ { if (self = [super init]) { - // create an INET socket that we'll be listen()ing on - int socketOpen = socket(PF_INET, SOCK_STREAM, 0); - - // create our address given the port - struct sockaddr_in address; - address.sin_family = AF_INET; - address.sin_port = htons(port); - address.sin_addr.s_addr = htonl(INADDR_ANY); - memset(address.sin_zero, '\0', sizeof(address.sin_zero)); - - // bind the socket... and don't give up until we've tried for a while - int tries = 0; - while (bind(socketOpen, (struct sockaddr *)&address, sizeof(address)) < 0) - { - if (tries >= 5) - { - close(socketOpen); - [_delegate errorEncountered: nil]; - return nil; - } - NSLog(@"couldn't bind to the socket... trying again in 5"); - sleep(5); - tries++; - } - [_delegate socketDidAccept]; - - // now we just have to keep our ears open - if (listen(socketOpen, 0) == -1) - { - [_delegate errorEncountered: nil]; - return nil; - } - - // accept a connection - struct sockaddr_in remoteAddress; - socklen_t remoteAddressLen = sizeof(remoteAddress); - _socket = accept(socketOpen, (struct sockaddr *)&remoteAddress, &remoteAddressLen); - if (_socket < 0) - { - close(socketOpen); - [_delegate errorEncountered: nil]; - return nil; - } - [_delegate socketDidAccept]; - - // we're done listening now that we have a connection - close(socketOpen); + _port = port; } return self; } @@ -107,6 +61,71 @@ _delegate = delegate; } +/** + * Connects to a socket on the port specified during init. This will dispatch another thread to do the + * actual waiting. Delegate notifications are posted along the way to let the client know what is going on. + */ +- (void)connect +{ + [NSThread detachNewThreadSelector: @selector(_connect:) toTarget: self withObject: nil]; +} + +/** + * This does the actual dirty work (in a separate thread) of connecting to a socket + */ +- (void)_connect: (id)obj +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + // create an INET socket that we'll be listen()ing on + int socketOpen = socket(PF_INET, SOCK_STREAM, 0); + + // create our address given the port + struct sockaddr_in address; + address.sin_family = AF_INET; + address.sin_port = htons(_port); + address.sin_addr.s_addr = htonl(INADDR_ANY); + memset(address.sin_zero, '\0', sizeof(address.sin_zero)); + + // bind the socket... and don't give up until we've tried for a while + int tries = 0; + while (bind(socketOpen, (struct sockaddr *)&address, sizeof(address)) < 0) + { + if (tries >= 5) + { + close(socketOpen); + [_delegate errorEncountered: nil]; + } + NSLog(@"couldn't bind to the socket... trying again in 5"); + sleep(5); + tries++; + } + + // now we just have to keep our ears open + if (listen(socketOpen, 0) == -1) + { + [_delegate errorEncountered: nil]; + } + + // accept a connection + struct sockaddr_in remoteAddress; + socklen_t remoteAddressLen = sizeof(remoteAddress); + _socket = accept(socketOpen, (struct sockaddr *)&remoteAddress, &remoteAddressLen); + if (_socket < 0) + { + close(socketOpen); + [_delegate errorEncountered: nil]; + } + + // we're done listening now that we have a connection + close(socketOpen); + + [_delegate performSelectorOnMainThread: @selector(socketDidAccept:) withObject: nil waitUntilDone: NO]; + //[_delegate socketDidAccept]; + + [pool release]; +} + /** * Reads from the socket and returns the result as a NSString (because it's always going to be XML). Be aware * that the underlying socket recv() call will *wait* for the server to send a message, so be sure that this @@ -187,4 +206,12 @@ [_delegate dataSent]; } +/** + * Helper method to simply post a notification to the default notification center with a given name and object + */ +- (void)_postNotification: (NSString *)name withObject: (id)obj +{ + [[NSNotificationCenter defaultCenter] postNotificationName: name object: obj]; +} + @end -- 2.22.5