Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
  Previous   Contents   Next 
   
 
Chapter 5

Advanced RPC Programming Techniques

This section addresses areas of occasional interest to developers using the lower-level interfaces of the RPC package. The topics are:

  • poll() on the server- How a server can call the dispatcher directly if calling svc_run() is not feasible

  • Broadcast RPC - How to use the broadcast mechanisms

  • Batching - How to improve performance by batching a series of calls

  • Authentication - What authentication methods are available in this release

  • Port monitors - How to interface with the inetd and listener port monitors

  • Multiple program versions - How to service multiple program versions

poll() on the Server Side

This section applies only to servers running RPC in single-threaded (default) mode.

A process that services RPC requests and performs some other activity cannot always call svc_run(). If the other activity periodically updates a data structure, the process can set a SIGALRM signal before calling svc_run(). This process enables the signal handler to process the data structure and return control to svc_run() when done.

A process can bypass svc_run() and access the dispatcher directly with the svc_getreqset() call. The process must be given the file descriptors of the transport endpoints associated with the programs being waited on. Then the process can have its own poll() that waits on both the RPC file descriptors and its own descriptors.

Example 5-1 shows svc_run(). svc_pollset is an array of pollfd structures that is derived, through a call to __rpc_select_to_poll(), from svc_fdset(). The array can change every time any RPC library routine is called because descriptors are constantly being opened and closed. svc_getreq_poll() is called when poll() determines that an RPC request has arrived on some RPC file descriptors.


Note - The __rpc_dtbsize() and __rpc_select_to_poll() functions are not part of the SVID, but they are available in the libnsl library. The descriptions of these functions are included here so that you can create versions of these functions for non-Solaris implementations.


Given an fd_set pointer and the number of bits to check in it, the __rpc_select_to_poll function initializes the supplied pollfd array for RPC's use. RPC polls only for input events. The number of pollfd slots that were initialized is returned. The arguments for this function are:

int __rpc_select_to_poll(int fdmax, fd_set *fdset,
					struct pollfd *pollset)

The __rpc_dtbsize() function calls the getrlimit() function to determine the maximum value that the system can assign to a newly created file descriptor. The result is cached for efficiency.

For more information on the SVID routines in this section, see the rpc_svc_calls(3NSL) and poll(2) man pages.


Example 5-1 svc_run() and poll()

void
svc_run()
{
	int nfds;
	int dtbsize = __rpc_dtbsize();
	int i;
	struct pollfd svc_pollset[fd_setsize];

	for (;;) {
		/*
		 * Check whether there is any server fd on which we may have
		 * to wait.
		 */
		nfds = __rpc_select_to_poll(dtbsize, &svc_fdset,
		                            svc_pollset);
		if (nfds == 0)
			break;	/* None waiting, hence quit */

		switch (i = poll(svc_pollset, nfds, -1)) {
		case -1:
			/*
			 * We ignore all errors, continuing with the assumption
			 * that it was set by the signal handlers (or any
			 * other outside event) and not caused by poll().
			 */
		case 0:
			continue;
		default:
			svc_getreq_poll(svc_pollset, i);
		}
	}
}

Broadcast RPC

When an RPC broadcast is issued, a message is sent to all rpcbind daemons on a network. An rpcbind daemon with which the requested service is registered forwards the request to the server. The main differences between broadcast RPC and normal RPC calls are:

  • Normal RPC expects one answer; broadcast RPC expects many answers, one or more answer from each responding machine.

  • Broadcast RPC works only on connectionless protocols that support broadcasting, such as UDP.

  • With broadcast RPC, all unsuccessful responses are filtered out. If a version mismatch occurs between the broadcaster and a remote service, the broadcaster is never contacted by the service.

  • Only datagram services registered with rpcbind are accessible through broadcast RPC. Service addresses can vary from one host to another, so rpc_broadcast() sends messages to rpcbind's network address.

  • The size of broadcast requests is limited by the maximum transfer unit (MTU) of the local network. The MTU for Ethernet is 1500 bytes.

The following code example shows how rpc_broadcast() is used and describes its arguments.


Example 5-2 RPC Broadcast

/*
 * bcast.c: example of RPC broadcasting use.
 */
 
#include <stdio.h>
#include <rpc/rpc.h>
 
main(argc, argv)
	int argc;
	char *argv[];
{
	enum clnt_stat rpc_stat;
	rpcprog_t prognum;
	rpcvers_t vers;
	struct rpcent *re;
 
	if(argc != 3) {
		fprintf(stderr, "usage : %s RPC_PROG VERSION\n", argv[0]);
		exit(1);
	}
	if (isdigit( *argv[1]))
		prognum = atoi(argv[1]);
	else {
		re = getrpcbyname(argv[1]);
		if (! re) {
			fprintf(stderr, "Unknown RPC service %s\n", argv[1]);
			exit(1);
		}
		prognum = re->r_number;
	}
	vers = atoi(argv[2]);
	rpc_stat = rpc_broadcast(prognum, vers, NULLPROC, xdr_void,
	           (char *)NULL, xdr_void, (char *)NULL, bcast_proc,
NULL);
	if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
		fprintf(stderr, "broadcast failed: %s\n",
		         clnt_sperrno(rpc_stat));
		exit(1);
	}
	exit(0);
}

 
 
 
  Previous   Contents   Next