1

I've given myself a headache trying to figure out how to run this Distributed Objects demo. I can run it just fine locally on the same machine.

Here's the situation. I have a Server App that spawns a Client App [with OpenGLView] on a remote machine.

I can do this easy with AppleScript.

The Client App seems to Vend it's OpenGLView window OK:

clientPort = [[NSSocketPort alloc] initWithTCPPort:SERVER_PORT];
if(clientPort == nil) continue; else NSLog(@"Port OK");

clientConnection = [NSConnection connectionWithReceivePort:clientPort sendPort:nil];
if(clientConnection == nil) continue; else NSLog(@"Conn OK");

[[NSSocketPortNameServer sharedInstance] registerPort:clientPort name:@"DOTest3_0"];

//Vend Object
@try {
[clientConnection setRootObject:object];
NSLog([NSString stringWithFormat:@"Port %d: Vend OK", (SERVER_PORT + i)]);
return;
} @catch (...) {
NSLog([NSString stringWithFormat:@"Port %d: Vend Next", (SERVER_PORT + i)]);
}

The Server App finds the Port and Connection, but Raises a TimeOut exception:

// Create temporary Pointer to kGLView Object.
  id <NSCoding, kGLViewProtocol> openGLView;

      // Setup Port, Connection, & Proxy
      portTest = (NSSocketPort *)[[NSSocketPortNameServer sharedInstance] portForName:@"DOTest3_0" host:@"*"];
      if (portTest == nil ) continue ; else NSLog(@"Port OK");

      connTest = [NSConnection  connectionWithReceivePort:nil sendPort:portTest];
      if (connTest == nil ) continue ; else NSLog(@"Conn OK");

      openGLView = [[connTest rootProxy] retain];
      if (openGLView == nil ) continue ; else NSLog(@"OpenGL OK");

      [openGLView drawWithRotation: rotationAngle];

  }

And I can't figure out for the life of Me WHY.

I get in the Console of the Client PC: "Port OK" "Conn OK" "Port 8081: Vend OK"

I get in the Console of the Server PC: "Port OK" "Conn OK" 11/18/09 2:05:36 PM DOTest3[15278] [NSPortCoder sendBeforeTime:sendReplyPort:] timed out (10280263936.092180 280263936.092642) 1

Even if the TimeOuts are both set to 60 seconds.

Help!

-Stephen


Server: MacMini OS X 10.5 Client: MacPro OS X 10.6 Remote Login, Management, etc. are all enabled.


EDIT: Taking NSResponder's suggestion, I've Vended the Controller, but it still isn't working.

Client/Vender:

-(void)vend:(id)object {
  port = [[[NSSocketPort alloc] initWithTCPPort:[self tcpPort]] 
          retain];

  conn = [[NSConnection connectionWithReceivePort:port sendPort:nil] 
          retain];

  for (int i = 0; i < 10; i++) {
    [[NSSocketPortNameServer sharedInstance] registerPort:port
                                                     name:[[self portName] stringByAppendingFormat:@"_%d", i]];
    @try {
      [conn setRootObject:object];
      return;
    } @catch (...) {
      NSLog(@"Vend Next");
      continue;
    }
  }
  NSLog(@"Vend Failed");
}

Client Controller:

-(id)init {
  self = [super init];

  [self setRotationAngle:0.0f];

  clientObj = [[Client alloc] initWithName:@"DOTest4" 
                                   Address:@"10.10.5.104" // mini
                                      Port:48557];

  [clientObj vend:self];

  return self;
}

Server Controller:

-(IBAction)rotateClient:(id)sender {
  NSArray *vendedObjects = [serverObj getVendedObjects];
  id <NSCoding, ClientController_Protocol> proxy;

  if (vendedObjects != nil) {
    for (int i = 0; i < [vendedObjects count]; i++) {
      proxy = [vendedObjects objectAtIndex:i];
      [proxy rotate];
    }
  }
    // release
  [vendedObjects release];
}

Server/(grabs Vended Objects)

-(NSArray *)getVendedObjects {

  NSArray *vendedObjects = [[[NSArray alloc] init] retain];
  NSSocketPort *port;
  NSConnection *conn;

  for (int i = 0; i< 10; i++) {
    // Get Port Object
    port = (NSSocketPort *)[[NSSocketPortNameServer sharedInstance] 
                           portForName:[[self portName] stringByAppendingFormat:@"_%d", i]
                           host:[self addressRemote]];
    if (port == nil) continue;
    // Create Connection with Timeouts
    conn = [NSConnection connectionWithReceivePort:nil sendPort:port];
    if (conn == nil) continue;

    [conn setReplyTimeout:(NSTimeInterval)60.0];
    [conn setRequestTimeout:(NSTimeInterval)60.0];

    // Get VendedObject of Connection
    vendedObjects = [[vendedObjects arrayByAddingObject:[conn rootProxy]] retain];
  }

  return vendedObjects;
}

Sigh... I'm sure I'm just overlooking something REALLY cocoa-basic here.

-S!

  • SIGH... that works. My problem was with returning the NSArray of NSDistance Objects. Something got dealloc'd in there somewhere. Performing the 'rotate' command in the 'getVendedObjects' method works just fine! -S – Stephen Furlani Nov 20 '09 at 16:53

1 Answers1

1

I've never seen anyone attempting to vend a view or a window across a DO link, and I'm surprised that it worked even on the local host. Anytime I've used DO, it's been from objects in the controller layer of the server to a corresponding controller in the client.

NSResponder
  • 16,861
  • 7
  • 32
  • 46
  • Ah, that's likely my problem then. Having the object in code and not in IB isn't a controller? – Stephen Furlani Nov 20 '09 at 12:40
  • I'm thoroughly confused by this comment. You should be able to vend ANY object right!? I haven't attempted this yet but will in the future. Thanks – manifest Apr 09 '10 at 18:08
  • 1
    You can vend a view or window just fine. The problem is that they don't draw into an object passed through Distributed Objects—they draw into a graphics context, and it's always the graphics context of the process that's vending the object. (This can even bite you with NSImage—make sure you pass those `bycopy`.) So you can vend a view across DO, and you can even usefully change its attributes, but you can't draw it into another app. – Becca Royal-Gordon Apr 29 '13 at 00:08