[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: a simple program
From: |
Richard Frith-Macdonald |
Subject: |
Re: a simple program |
Date: |
Thu, 16 Aug 2001 20:01:55 +0000 |
On Thursday, August 16, 2001, at 04:43 PM, Aurelien wrote:
Hi,
I'm new to GnuStep (though I've already written a small graphics app in
Cocoa), and I'd like to play a bit with it for server-side programming.
In fact, I'm evaluating writing an Obj-C port of the JXTA platform. For
that, I'd need some help with networking/multi-threading.
The following program (written in java) is a simple chat server I wrote
some time ago for a client. See how small it is (it took ma about an
hour to write, test, deploy) !
To me, writing something like this in Obj-C still appears like a
challenge...
Prove me wrong, please ;-) In particular, I'd like to know how to deal
with the multi-threading part.
First ... you can do GNUstep coding in Java if you want ... we have a
Java interface which works
very well and lets you use ObjC classes from Java code and vice versa.
Second ... you have not chosen a 'fair' example. The given task is
something where Java is at it's
best - so you might expect the Java code to be more compact and easy to
write.
That being said, in the spirit of your original code (a quick hack
together where you aren't really
concerned about stability etc, just want to get something working), I
spent half an hour writing
something similar in ObjC. Please note, disclaimers ...
1. This is not reliable code ... it suffers from the same problems of
multiple threads accessing the
same datastructure in an unsafe way that the java code does.
2. This is not good safe code ... it could be written to trap and handle
problems more gracefully.
3. This is not well designed code ... it would be written with nice new
classes designed with
extensibility and clarity in mind.
4. This really abuses categories for a quick hack ... I wouldn't do that
for a real program - but it
allowed me to make the program shorter and perhaps simpler to follow.
5. In a real heavy-duty server, I would avoid the use of threads
altogether, I only really used them
for simplicity and because you asked for it. As you can see, the use of
threading is trivial.
The basic algorithm is the same as in your version.
Two methods are added to the NSFileHandle class ... one to repeatedly
accept incoming
connections and store their file handles in the clients array, one to
run in new threads.
Note ... The macros for autorelease handling are there to prevent memory
leaks ... something
you don't need to worry about in Java, but something that gives you more
control than in Java.
If you did want to make this really robust, you would need to use an
NSLock to synchronize
access to the clients array, in a similar ay to that in which you would
use 'synchronize'
to make the original java code more reliable.
#include <Foundation/Foundation.h>
NSMutableArray *clients;
@interface NSFileHandle (MyCategory)
- (void) accepted: (NSNotification*)notification;
- (void) run;
@end
@implementation NSFileHandle (MyCategory)
- (void) accepted: (NSNotification*)notification
{
NSDictionary *userInfo = [notification userInfo];
NSFileHandle *hdl;
hdl = [userInfo objectForKey: NSFileHandleNotificationFileHandleItem];
if (hdl == nil)
{
NSLog(@"Bad handle in 'accepted:' ... terminating.");
RELEASE(self);
}
[clients addObject: hdl];
[NSThread detachNewThreadSelector: @selector(run)
toTarget: hdl
withObject: nil];
[self acceptConnectionInBackgroundAndNotify];
}
- (void) run
{
CREATE_AUTORELEASE_POOL(pool);
NSData *data;
NS_DURING
{
while ([(data = [self availableData]) length] > 0)
{
NSEnumerator *e = [clients objectEnumerator];
NSFileHandle *h;
NS_DURING
{
while ((h = [e nextObject]) != nil && h != self)
{
[h writeData: data];
}
}
NS_HANDLER
{
NSLog(@"Exception writing to client ... %@", localException);
}
NS_ENDHANDLER
}
}
NS_HANDLER
{
NSLog(@"Exception reading from client ... %@", localException);
}
NS_ENDHANDLER
[clients removeObjectIdenticalTo: self];
RELEASE(pool);
}
@end
int main ()
{
CREATE_AUTORELEASE_POOL(pool);
NSNotificationCenter *nc;
NSFileHandle *listener;
clients = [NSMutableArray arrayWithCapacity: 16];
listener = [NSFileHandle fileHandleAsServerAtAddress: nil
service: @"6401"
protocol: @"tcp"];
nc = [NSNotificationCenter defaultCenter];
[nc addObserver: listener
selector: @selector(accepted:)
name: NSFileHandleConnectionAcceptedNotification
object: listener];
[listener acceptConnectionInBackgroundAndNotify];
[[NSRunLoop currentRunLoop] run];
RELEASE(pool);
return 0;
}
- a simple program, Aurelien, 2001/08/16
- Re: a simple program,
Richard Frith-Macdonald <=