Lecture Notes for Client-Server Interfaces

25 March 2004 - 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 17 January 2004.