Next: 6 Putting them together Up: 5 The client Previous: 5.1 The FileReader protocol

5.2 Accessing the remote FileReader object

To access the reader object, where we used to create it directly,
reader = [FileReader new];
we now ask the gnustep-base library to give us the object registered with the name FileReader on a remote machine:
reader = (id <FileReader>)[NSConnection
               rootProxyForConnectionWithRegisteredName: @"FileReader" 
               host: @"*"];
strictly speaking, reader is a local proxy to the remote object - but the whole thing is made so that you can forget about this distinction, and think of reader simply as the remote object. Using * for the host argument means that gnustep-base will look for an object registered with name FileReader anywhere on the network; if you know the host on which you want to access the FileReader object, you should better use your specific host name, such as localhost or 192.14.29.1.

We need a cast to id <FileReader> because the call to NSConnection returns a generic object, while we know the FileReader object implements getFile:. A more robust application could check at execution time that the remote object in the server actually can respond to getFile: messages before doing the cast (for example by using the method respondsToSelector:); we skip this little complication in this first example.

But we need to check that we have a real reader object - if it is nil, it is because for some reason the gnustep-base library couldn't connect to an object registered as FileReader on the network. Usually this is because the server is not running; there is nothing we can do in the client in these cases, so we simply print an error message and exit.

As promised, the rest of the function is unchanged; in particular, when we send the getFile: method to the remote object, that starts a network connection to the server, and returns the result - but the nice thing is that we don't need to do anything special to perform this remote call: we just call the method normally, as if the object were our old friendly local object.

Here is the source code:

#include <Foundation/Foundation.h>

/* This tells us how the reader object behaves */

@protocol FileReader
- (NSString *)getFile: (NSString *)fileName;
@end


int 
main (void)
{
  NSAutoreleasePool *pool;
  NSArray *args;
  int count;
  id <FileReader> reader;
  NSString *filename;
  NSString *file;

  pool = [NSAutoreleasePool new];

  /* Create our FileReader object */
  reader = (id <FileReader>)[NSConnection
             rootProxyForConnectionWithRegisteredName: 
                   @"FileReader" 
             host: @"*"];

  if (reader == nil)
    {
      NSLog (@"Error: could not connect to server");
      exit (1);
    }
  
  /* From now on the code is the same, whether reader is 
     in the local process or in a remote one */

  /* Get program arguments */
  args = [[NSProcessInfo processInfo] arguments];

  /* the first string in args is the program name; 
     get the second one if any */
  if ([args count] == 1)
    {
      NSLog (@"Error: you should specify a filename");
      exit (1);
    }
  
  filename = [args objectAtIndex: 1];

  /* Ask the reader object to get the file */
  file = [reader getFile: filename];

  /* If the reader object could get the file, show it */
  if (file != nil)
    {
      printf ("%s\n", [file lossyCString]);
    }
  else
    {
      NSLog (@"Error: could not read file `%@'", filename);
      exit (1);
     }

  return 0;
}


Next: 6 Putting them together Up: 5 The client Previous: 5.1 The FileReader protocol
2008-01-16