Lecture Notes for Client-Server Interfaces

25 March 2003 - The Horrible Truth About RPC


The Three Faces of RPC


High-Level Access to RPC


RPC Library Routines


And Then. . .

$ make cc-high-rstat
g++ -c cc-high-rstat.cc -o cc-high-rstat.o
g++ -o cc-high-rstat cc-high-rstat.o -lrpcsvc

$ uname -a
SunOS clayton 5.7 Generic_106541-11 sun4u 
sparc SUNW,Ultra-5_10

$ cc-high-rstat cslab05
cslab05 has a disk.

$ cc-high-rstat clayton 
clayton has a disk.

$ cc-high-rstat starbase.se.monmouth.edu
starbase.se.monmouth.edu has a disk.

$ cc-high-rstat cslab00                 
havedisk(cslab00) failed.

$ rsh cslab00 ps -Af | grep -i rpc
  root  156    1  0 /usr/sbin/rpcbind
  root  186    1  0 /usr/lib/netsvc/yp/rpc.ypupdated
  root  171  169  0 rpc.nisd_resolv -F -C 8 
  root  667    1  0 /usr/sbin/rpc.bootparamd
  root  785  213  0 /usr/dt/bin/rpc.ttdbserverd

$ rsh cslab05 ps -Af | grep -i rpc
  root  105    1  0 /usr/sbin/rpcbind
  root  338  142  0 rpc.ttdbserverd
daemon  537  142  0 rpc.cmsd
  root 2835  142  0 rpc.rstatd


The Middle-Level API


The Client Middle-Level API


Using the Client

$ gcc -o rusers rusers.c -lrpcsvc -lnsl

$ ./rusers cslab18
0 users on cslab18.

$ ./rusers cslab00
38 users on cslab00.

$ ./rusers enterprise.se.monmouth.edu
RPC: Program/version mismatch

$ ./rusers rockhopper.monmouth.edu   
RPC: Program not registered

$ ./rusers moncol.monmouth.edu    
RPC: Program not registered

$ ./rusers bluehawk.monmouth.edu
RPC: Program/version mismatch

$ 


The Server Interface


An Encrypt-Service Client


The Middle Level

#include <stdio.h>
#include <stdlib.h>
#define PORTMAP
#include <rpc/rpc.h>
#include <rpcsvc/rstat.h>
#include <rpc/xdr.h>

int main(int argc, char * argv[]) {

  if (argc != 2) {
    fprintf(stderr, "Command format is \"%s hostname\".\n", argv[0]);
    return EXIT_FAILURE;
    }

  int dsk;
  enum clnt_stat stat = callrpc(
    argv[1], RSTATPROG, RSTATVERS_VAR, RSTATPROC_HAVEDISK, 
    xdr_void, 0, xdr_u_long, &dsk);
  if (stat) {
    clnt_perrno(stat);
    return EXIT_FAILURE;
    }

  printf("%s %s a disk.\n", argv[1], dsk ? "has" : "doesn't have");

  return EXIT_SUCCESS;
  }


Fun with RPC

$ make cc-mid-rstat
g++    -c cc-mid-rstat.cc -o cc-mid-rstat.o
g++ -o cc-mid-rstat cc-mid-rstat.o -lnsl

$ cc-mid-rstat clayton
clayton has a disk.

$ cc-mid-rstat cslab05
cslab05 has a disk.

$ cc-mid-rstat starbase.se.monmouth.edu
RPC: Program/version mismatch

$ 


The Low Level

int main(int argc, char * argv[]) {

  struct hostent *hp;
  if ((hp = gethostbyname(argv[1])) == NULL) {
    fprintf(stderr, "can't get addr for %s\n",argv[1]);
    return EXIT_FAILURE;
    }

  int sock = RPC_ANYSOCK;
  struct timeval pertry_timeout, total_timeout;
  struct sockaddr_in server_addr;

  pertry_timeout.tv_sec = 3;
  pertry_timeout.tv_usec = 0;
  bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr, hp->h_length);
  server_addr.sin_family = AF_INET;
  server_addr.sin_port =  0;

  CLIENT *client = clntudp_create(&server_addr, RSTATPROG,
				  RSTATVERS_VAR, pertry_timeout, &sock);
  if (NULL == client) {
    clnt_pcreateerror("clntudp_create");
    return EXIT_FAILURE;
    }

  total_timeout.tv_sec = 20;
  total_timeout.tv_usec = 0;
  unsigned long dsk;
  enum clnt_stat stat = clnt_call(client, RSTATPROC_HAVEDISK,
				  (bool_t (*)(XDR *, void *)) xdr_void, 0,
				  xdr_u_long, (char *) &dsk, 
				  total_timeout);
  if (stat != RPC_SUCCESS) {
    clnt_perror(client, "rpc");
    return EXIT_FAILURE;
    }

  printf("%s %s a disk.\n", argv[1], dsk ? "has" : "doesn't have");

  clnt_destroy(client);
  close(sock);

  return EXIT_SUCCESS;
  }


Just Checking

$ cc-low-rstat cslab05
cslab05 has a disk.

$ cc-low-rstat cslab00
clntudp_create: RPC: Program not registered

$ cc-low-rstat starbase.se.monmouth.edu
rpc: RPC: Program/version mismatch; low version = 1, high version = 3

$ 


Why Three Levels?


The Server Side


This page last modified on 2 March 2002.