Re: Distributed Objects pitfalls and strategies
Re: Distributed Objects pitfalls and strategies
- Subject: Re: Distributed Objects pitfalls and strategies
- From: Wade Tregaskis <email@hidden>
- Date: Wed, 31 Mar 2004 00:33:08 +1000
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-
DO should be pretty tough if used properly - I've used it for all sorts
of things without any major issues.
-- 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];
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.
You can set the message reply timeout on the NSConnection. By default
it is either 10, 60 or never, depending on what mood NSConnection is in
when you init it. Depending on your intended use you may want timeouts
anywhere between a few seconds and a few minutes. From the fact that
this is a problem for you I imagine a few seconds is more likely what
you want.
But that won't solve all your problems. You should try to write your
DO stuff to be as asynchronous as possible (using oneway void and
bycopy as much as you can). This will help stop either side locking up
if the other takes a while and/or dies. You should also try to
separate your networking into a separate thread to your UI, as with any
network app, to ensure the lock ups don't translate to your app
freezing.
As for the port not being reusable immediately, that's one I've never
actually seen myself. It's been brought up ad infinum on many lists.
The solution is probably to create the sockets manually and set the
appropriate port option, as you do... you could try setting it after
creating the ports automatically, although from memory setsockopt
doesn't do much to ports already in use.
-- 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.
I'm not familiar with the behaviour for users switching, but I'm pretty
sure no processes ever get paused or otherwise put on old. Why exactly
is your server process starting and stopping when users log in and out?
The client hanging can be treated using the suggestions I spoke of
above.
-- 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.
*boggle* That's a big of a disaster, innit? I've never heard that one
before... I've had multiple servers [of the same type, using the same
port] running concurrently without any such trouble. Of course, in
that particular scenario I've never created the sockets myself...
perhaps you're not configuring something correctly, or somesuch? I'm
not big on raw sockets, so I can't really suggest anything.
I'm not sure how TCP connections could cross over as you describe; I'm
pretty sure they can't. Which implies the connection is being
frequently remade, and to the wrong address... or something. Do you
have any more details on this problem?
-- 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.
Indeed. For a LAN app this is in fact ideal, given the availability of
Rendezvous and the flexibility it provides (e.g. multiple concurrent
servers on a single computer).
So what is the right way to do this?
Well.. the thought arises as to why you need to reuse the port all the
time... you're not creating a new server instance after each connection
are you? If you need to serve different objects to different clients
(i.e. one 'server' task per client connection) then you should setup a
gateway object to server, which all clients connect to initially, and
then that can return a unique instance of your tailor-made server
object on the client's request.
That of course still won't help if you do have a valid reason to be
regularly tearing down your server, but I suspect this probably isn't
the case. Can you provide any more details as to what and how you're
trying to do things? Perhaps you can avoid the problems you're
experiencing by taking a slightly different approach.
Wade Tregaskis
-- Sed quis custodiet ipsos custodes?
_______________________________________________
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.