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 an empty string for the host argument means that gnustep-base will look for an object registered with name FileReader on the local host; if you know the host on which you want to access the FileReader object, you should better use your specific host name, such 192.168.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
2011-02-09