Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
4.  Programmer's Interface to RPC Simplified Interface Passing Arbitrary Data Types  Previous   Contents   Next 
   
 

The following list shows prefabricated routines:

xdr_array()
xdr_bytes()
xdr_reference()
xdr_vector()
xdr_union()
xdr_pointer()
xdr_string()
xdr_opaque()

For example, to send a variable-sized array of integers, the routine is packaged in a structure containing the array and its length:

struct varintarr {
 	int *data;
 	int arrlnth;
 } arr;

Translate the array with xdr_varintarr(), as shown in the following code example.


Example 4-4 xdr_varintarr Syntax Use

bool_t
xdr_varintarr(xdrsp, arrp)
	XDR *xdrsp;
	struct varintarr *arrp;
{
	return(xdr_array(xdrsp, (caddr_t)&arrp->data,
		(u_int *)&arrp->arrlnth, MAXLEN,
		sizeof(int), xdr_int));
}

The arguments of xdr_array() are the XDR handle, a pointer to the array, a pointer to the size of the array, the maximum array size, the size of each array element, and a pointer to the XDR routine to translate each array element. If the size of the array is known in advance, use xdr_vector(), as shown in the following code example.


Example 4-5 xdr_vector Syntax Use

int intarr[SIZE];

bool_t
xdr_intarr(xdrsp, intarr)
	XDR *xdrsp;
	int intarr[];
{
	return (xdr_vector(xdrsp, intarr, SIZE,
				sizeof(int),
xdr_int));
}

XDR converts quantities to 4-byte multiples when serializing. For arrays of characters, each character occupies 32 bits. xdr_bytes() packs characters. It has four parameters similar to the first four parameters of xdr_array().

Null-terminated strings are translated by xdr_string(), which is like xdr_bytes() with no length parameter. On serializing xdr_string() gets the string length from strlen(), and on deserializing it creates a null-terminated string.

The following example calls the built-in functions xdr_string() and xdr_reference(), which translates pointers to pass a string, and struct simple from previous examples.


Example 4-6 xdr_reference Syntax Use

struct finalexample {
	char *string;
	struct simple *simplep;
} finalexample;

bool_t
xdr_finalexample(xdrsp, finalp)
	XDR *xdrsp;
	struct finalexample *finalp;
{
	if (!xdr_string(xdrsp, &finalp->string,
			MAXSTRLEN))
		return (FALSE);
	if (!xdr_reference( xdrsp, &finalp->simplep,
			sizeof(struct simple), xdr_simple))
		return (FALSE);
	return (TRUE);

}

Note that xdr_simple() could have been called here instead of xdr_reference().

Standard Interfaces

Interfaces to standard levels of the RPC package provide increasing control over RPC communications. Programs that use this control are more complex. Effective programming at these lower levels requires more knowledge of computer network fundamentals. The top, intermediate, expert, and bottom levels are part of the standard interfaces.

This section describes how to control RPC details by using lower levels of the RPC library. For example, you can select the transport protocol, which can be done at the simplified interface level only through the NETPATH variable. You should be familiar with the top-level interface (TLI) in order to use these routines.

The routines shown below cannot be used through the simplified interface because they require a transport handle. For example, there is no way to allocate and free memory while serializing or deserializing with XDR routines at the simplified interface.

clnt_call()
clnt_destroy()
clnt_control()
clnt_perrno()
clnt_pcreateerror()
clnt_perror()
svc_destroy()

Top-Level Interface

At the top level, the application can specify the type of transport to use but not the specific transport. This level differs from the simplified interface in that the application creates its own transport handles in both the client and server.

Client Side of the Top-Level Interface

Assume the header file in the following code example.


Example 4-7 time_prot.h Header File

/* time_prot.h */

#include <rpc/rpc.h>
#include <rpc/types.h>
 
struct timev {
	int second;
	int minute;
	int hour;
};
typedef struct timev timev;
bool_t xdr_timev();
 
#define TIME_PROG 0x40000001
#define TIME_VERS 1
#define TIME_GET  1

The following example shows the client side of a trivial date service using top-level service routines. The transport type is specified as an invocation argument of the program.


Example 4-8 Client for Trivial Date Service

#include <stdio.h>
#include "time_prot.h"
 
#define TOTAL (30)
/*
 * Caller of trivial date service
 * usage: calltime hostname
 */
main(argc, argv)
	int argc;
	char *argv[];
{
	struct timeval time_out;
	CLIENT *client;
	enum clnt_stat stat;
	struct timev timev;
	char *nettype;
 
	if (argc != 2 && argc != 3) {
		fprintf(stderr,"usage:%s host[nettype]\n"
					,argv[0]);
		exit(1);
	}
	if (argc == 2)
		nettype = "netpath";		/* Default */	
	else
		nettype = argv[2];
	client = clnt_create(argv[1], TIME_PROG,
									TIME_VERS, nettype);
	if (client == (CLIENT *) NULL) {
		clnt_pcreateerror("Couldn't create client");
		exit(1);
	}
	time_out.tv_sec = TOTAL;
	time_out.tv_usec = 0;
	stat = clnt_call( client, TIME_GET, 
					xdr_void, (caddr_t)NULL,
					xdr_timev, (caddr_t)&timev,
					time_out);
	if (stat != RPC_SUCCESS) {
		clnt_perror(client, "Call failed");
		exit(1);
	}
	fprintf(stderr,"%s: %02d:%02d:%02d GMT\n",
				nettype timev.hour, timev.minute,
				timev.second);
	(void) clnt_destroy(client);
	exit(0);	
}

 
 
 
  Previous   Contents   Next