Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
4.  Programmer's Interface to RPC Standard Interfaces Top-Level Interface Client Side of the Top-Level Interface  Previous   Contents   Next 
   
 

If nettype is not specified in the invocation of the program, the string netpath is substituted. When RPC libraries routines encounter this string, the value of the NETPATH environment variable governs transport selection.

If the client handle cannot be created, display the reason for the failure with clnt_pcreateerror(). You can also get the error status by reading the contents of the global variable rpc_createerr.

After the client handle is created, clnt_call() is used to make the remote call. Its arguments are the remote procedure number, an XDR filter for the input argument, the argument pointer, an XDR filter for the result, the result pointer, and the time-out period of the call. The program has no arguments, so xdr_void() is specified. Clean up by calling clnt_destroy().

To bound the time allowed for client handle creation in the previous example to 30 seconds, replace the call to clnt_create() with a call to clnt_create_timed() as shown in the following code segment:

 struct timeval timeout;
 timeout.tv_sec = 30;		/* 30 seconds */
 timeout.tv_usec = 0;

 client = clnt_create_timed(argv[1],
					TIME_PROG, TIME_VERS, nettype,
					&timeout);

The following example shows a top-level implementation of a server for the trivial date service.


Example 4-9 Server for Trivial Date Service

#include <stdio.h>

#include <rpc/rpc.h>
#include "time_prot.h"
 
static void time_prog();
 
main(argc,argv)
	int argc;
	char *argv[];
{
	int transpnum;
	char *nettype;
 
	if (argc > 2) {
 
		fprintf(stderr, "usage: %s [nettype]\n",
						argv[0]);
		exit(1);
	}
	if (argc == 2)
		nettype = argv[1];
	else
		nettype = "netpath";			/* Default */
	transpnum =
svc_create(time_prog,TIME_PROG,TIME_VERS,nettype);
	if (transpnum == 0) {
		fprintf(stderr,"%s: cannot create %s service.\n",
					argv[0], nettype);
		exit(1);
	}
	svc_run();
}
 
/*
 * The server dispatch function
 */
static void
time_prog(rqstp, transp)
	struct svc_req *rqstp;
	SVCXPRT *transp;
{
	struct timev rslt;
	time_t thetime;
 
	switch(rqstp->rq_proc) {
		case NULLPROC:
			svc_sendreply(transp, xdr_void, NULL);
			return;
		case TIME_GET:
			break;
		default:
			svcerr_noproc(transp);
			return;
		}
	thetime = time((time_t *) 0);
	rslt.second = thetime % 60;
	thetime /= 60;
	rslt.minute = thetime % 60;
	thetime /= 60;
	rslt.hour = thetime % 24;
	if (!svc_sendreply( transp, xdr_timev, &rslt)) {
		svcerr_systemerr(transp);
		}
}

svc_create() returns the number of transports on which it created server handles. time_prog() is the service function called by svc_run() when a request specifies its program and version numbers. The server returns the results to the client through svc_sendreply().

When you use rpcgen to generate the dispatch function, svc_sendreply() is called after the procedure returns. Therefore, rslt in this example must be declared static in the actual procedure. svc_sendreply() is called from inside the dispatch function, so rslt is not declared static.

In this example, the remote procedure takes no arguments. When arguments must be passed, the calls listed below fetch, deserialize (XDR decode), and free the arguments.

svc_getargs( SVCXPRT_handle, XDR_filter, argument_pointer);
svc_freeargs( SVCXPRT_handle, XDR_filter argument_pointer );

Intermediate-Level Interface

At the intermediate level, the application directly chooses the transport to use.

Client Side of the Intermediate-Level Interface

The following example shows the client side of the time service from "Top-Level Interface", written at the intermediate level of RPC. In this example, the user must name the transport over which the call is made on the command line.


Example 4-10 Client for Time Service, Intermediate Level

#include <stdio.h>

#include <rpc/rpc.h>
#include <netconfig.h>		/* For netconfig structure */
#include "time_prot.h"
 
#define TOTAL (30)
 
main(argc,argv)
	int argc;
	char *argv[];
{
	CLIENT *client;
	struct netconfig *nconf;
	char *netid;
	/* Declarations from previous example */
 
	if (argc != 3) {
		fprintf(stderr, "usage: %s host netid\n",
					argv[0]);
		exit(1);
	}
	netid = argv[2];
	if ((nconf = getnetconfigent( netid)) ==
 
	    (struct netconfig *) NULL) {
		fprintf(stderr, "Bad netid type: %s\n",
					netid);
		exit(1);
	}
	client = clnt_tp_create(argv[1], TIME_PROG,
										TIME_VERS, nconf);
	if (client == (CLIENT *) NULL) {
		clnt_pcreateerror("Could not create client");
		exit(1);
	}
	freenetconfigent(nconf);
 
	/* Same as previous example after this point */
}

 
 
 
  Previous   Contents   Next