Re: Distributed Objects pitfalls and strategies
Re: Distributed Objects pitfalls and strategies
- Subject: Re: Distributed Objects pitfalls and strategies
- From: Aurélien Hugelé <email@hidden>
- Date: Tue, 30 Mar 2004 17:57:09 +0200
On 30 Mar 2004, at 10:44, John Scalo wrote:
>
Is there any reliable and resilient way to set up a DO server/client?
>
By reliable and resilient, I mean something that can withstand server
>
stops and starts, multiple user logout/logins, Panther fast user
>
switching, and deals with multiple clients and servers running on the
>
same network. It's not hard to get something that works most of the
>
time, but that's not good enough in this case. I've tried a few
>
different strategies, but each has its problems. From an earlier
>
discussion, the solution seemed to be to set up the BSD socket
>
manually and set the option to allow port reuse. But that introduces
>
more issues. Here are the things I've tried-
yes i have heard about the port reuse too, but it seems too complex for
me...
>
>
-- Neither client or server is set to reuse ports -- (aka Plain Ol'
>
Distributed Objects)
>
i.e. the server does this:
>
NSSocketPort *newPort = [[NSSocketPort alloc] initWithTCPPort:MYPORT];
>
NSConnection *connection = [[NSConnection alloc]
>
initWithReceivePort:newPort sendPort:newPort];
>
and the client does this:
>
NSSocketPort *connectionPort = [[NSSocketPort alloc]
>
initRemoteWithTCPPort:MYPORT host:ipAddressString];
>
NSConnection *connection = [[NSConnection alloc]
>
initWithReceivePort:NULL sendPort:connectionPort];
>
this is the solution i used and it works reasonably well, except that i
added RendezVous in the process, like this, the port is not always the
same ( => no problem when creating a connection with a port that was
just used, but crashed in the last 120 seconds (the tcp timeout for an
unused port/socket IIRC)) Of course the problem here is that my program
now only works on lan :(
>
Problems:
>
* Client hangs when server disappears and then generates timeout
>
exceptions.
>
* Server can't make new NSSocketPorts after successive user
>
logout/logins for about 10 minutes.
for your first problem, i used a simple solution, somewhat not very
nice and not always applicable :
just before communicating with the server AND WHEN I MUST HAVE A RETURN
VALUE (ie synchronous return value), i set a very low timeout for the
connection (about 5 second) and send the server a " - (bool) isAlive"
message. If the server anser YES, i immediatly messages it... . At the
same time, I catch the timeout exception and retry the message few
seconds later... after 10 tries, i declare the server dead and stop
communication with it... this is far from perfect but works quite well
I try, when possible, to use the oneway attribute a lot to avoid the
hanging problems : i send most of my messages as oneway, and
asynchronously, in another thread, the server answers the client as
oneway too ! no more hangs !
this is quite complex to design and sometimes it is not possible to do
at all :( but it is the best solution i have found...
>
>
-- Server set to reuse ports --
>
i.e. the server uses initWithProtocolFamily and the client uses
>
initRemoteWithProtocolFamily, setting up their own BSD socket
>
bind()ing, and listen()ing. Each calls setsockopt(newSocket,
>
SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) before binding.
>
>
Problems:
>
* Client hangs and gets timeout exceptions trying to resolve
>
connections after the server process has been stopped and started
>
again. e.g., a user logs out and another logs in.
so basically, the reuse of port does not work ? since the connection
can't be resolved, i suppose the port has not really been reused ? or
the connection is not only based on the port ?
>
>
-- Both set to reuse ports --
>
Problems:
>
* If there are multiple servers running on the network, then messages
>
sent to a connection's proxy go to a random server, not necessarily
>
the one the NSSocketPort was created for.
>
ouch... i wonder how to solve this problem... i think Cocoa's DO are
not evolved enough ?
>
-- Use dynamic private ports --
>
Since port #s are unique, there isn't an issue of making new
>
connections, but this isn't workable if the user has a firewall, or
>
outside the local network.
i agree, strong limitation !
>
>
So what is the right way to do this?
the huge lack of support from Apple on this problem is very
frustrating... except the very little piece of code given by Chris Kane
on how to make DO, there is absolutly no other piece of code showing
how to design a *both way* (ala peer to peer) communication between DO
servers and clients... i have found most answer to my question by
asking on this list, they were written by NextStep old users ;)
i noticed that *nobody* has a clear comprehension of how do DO are
actually implemented...
basically my method to implement *both way* communication using DO is
always the same :
SERVER :
1/i start a server connection and set the root object in a thread.
2/ the server publish a rendezVous service to show its presence using
the port number of the connection created just above
3/ i make the thread "run almost forever" by looping as this :
while(shouldContinueLooping && [theThreadRunLoop
runMode:NSConnectionReplyMode beforeDate:[[NSDate date]
addTimeInterval:1.0]])
like this the server thread stops only when the "shouldContinueLooping"
pass to NO... i dont know why but the run...untildate: variant does not
work, i MUST use the run...beforeDate: variant...
so the thread is listening to client requests until you pass
shouldContinueLooping to NO.
CLIENT CONTROLLER (singleton) :
1/ the client controller register for the rendezVous service published
by the server
2/ when resolving the rdv service, start a thread that create a
communication to the server port and keep the rootProxy (the server)
3/ create a CLIENT INSTANCE, pass it the server port and ip address,
the rootProxy
CLIENT INSTANCE :
1/ establish a connection with the server using passed infos above
2/ ask the server to register us ! (passing the server the client IP
Address and the client port)
SERVER AGAIN :
1/ check the CLIENT INSTANCE is not already registered etc...
2/ start a connection to the CLIENT INSTANCE to get its rootProxy (you
should use enableMultipleThreads method here, but not the
runInNewThread ! (it consumes 100% of the CPU !???))
END :
you now have a *BOTH WAY* (ala peer to peer), fully threaded,
comunication between server and clients. you can have several servers
on you lan, they see each other via rendezVous and don't have the same
ports...
i know this seems quite complex but it is very stable here with about
10 servers/ 10 clients (never tested more...) i sometimes have
Exception problem with timeout when a server crashes (the DO is only a
small part of the App and is not the source of the crashes ;) ) or the
App is force-quitted...
What is nice with this peer to peer communication is that when a client
quits, it can warn the server to unregister it (=> the server won't
hang or timeout when trying to talk with dead clients) and the clients
are warned too when the server die...
using the little bad tricks i explained at the beginning of this mail,
i succeeded to minimize the timeout exception and hanging problem to
the *very* little...
i hope this helps in designing quite complex, but robust DO
communications...
i would enjoy receiving remarks, comment or critics since i designed
this architecture alone, without any help or experience from anybody
(except from few very nice person of this list of course !!!!) i'm
quite proud of the results but it is the first time i expose it ! It is
absolutly possible that this architecture is a mess, overcomplicated,
and i would like to know why !
thanks to think and comment this !
>
>
Thanks
>
~ John
>
_______________________________________________
>
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.
_______________________________________________
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.