JavaScript is required to for searching.
Skip Navigation Links
Exit Print View
ONC+ Developer's Guide     Oracle Solaris 11.1 Information Library
search filter icon
search icon

Document Information

Preface

1.  Introduction to ONC+ Technologies

2.  Introduction to TI-RPC

3.  rpcgen Programming Guide

4.  Programmer's Interface to RPC

5.  Advanced RPC Programming Techniques

poll() on the Server Side

Broadcast RPC

Batching

Authentication

AUTH_SYS Authentication

AUTH_DES Authentication

AUTH_KERB Authentication

Authentication Using RPCSEC_GSS

RPCSEC_GSS API

RPCSEC_GSS Routines

Creating a Context

Changing Values and Destroying a Context

Principal Names

Setting Server Principal Names

Generating Client Principal Names

Freeing Principal Names

Receiving Credentials at the Server

Cookies

Callbacks

Maximum Data Size

Miscellaneous Functions

Associated Files

gsscred Table

/etc/gss/qop and /etc/gss/mech

Using Port Monitors

Using inetd

Using the Listener

Multiple Server Versions

Multiple Client Versions

Using Transient RPC Program Numbers

6.  Porting From TS-RPC to TI-RPC

7.  Multithreaded RPC Programming

8.  Extensions to the Oracle Solaris RPC Library

A.  XDR Technical Note

B.  RPC Protocol and Language Specification

C.  XDR Protocol Specification

D.  RPC Code Examples

E.  portmap Utility

Glossary

Index

Batching

RPC is designed so that clients send a call message and wait for servers to reply to the call. This procedure implies that a client is blocked while the server processes the call. This result is inefficient when the client does not need each message acknowledged.

RPC batching lets clients process asynchronously. RPC messages can be placed in a pipeline of calls to a server. Batching requires that:

Because the server does not respond to each call, the client can send new calls in parallel with the server processing previous calls. The transport can buffer many call messages and send them to the server in one write() system call. This buffering decreases interprocess communication overhead and the total time of a series of calls. The client should end with a nonbatched call to flush the pipeline.

The following code example shows the unbatched version of the client. It scans the character array, buf, for delimited strings and sends each string to the server.

Example 5-4 Unbatched Client

#include <stdio.h>
#include <rpc/rpc.h>
#include "windows.h"
 
main(argc, argv)
    int argc;
    char **argv;
{
    struct timeval total_timeout;
    register CLIENT *client;
    enum clnt_stat clnt_stat;
    char buf[1000], *s = buf;
 
    if ((client = clnt_create( argv[1], WINDOWPROG, WINDOWVERS,
                    "circuit_v")) == (CLIENT *) NULL) {
        clnt_pcreateerror("clnt_create");
        exit(1);
    }
 
    total_timeout.tv_sec = 20;
    total_timeout.tv_usec = 0;
    while (scanf( "%s", s ) != EOF) {
        if (clnt_call(client, RENDERSTRING, xdr_wrapstring, &s,
           xdr_void, (caddr_t) NULL, total_timeout) != RPC_SUCCESS) {
            clnt_perror(client, "rpc");
            exit(1);
        }
    }
 
    clnt_destroy( client );
    exit(0);
}

The following code example shows the batched version of the client. It does not wait after each string is sent to the server. It waits only for an ending response from the server.

Example 5-5 Batched Client

#include <stdio.h>

#include <rpc/rpc.h>
#include "windows.h"
 
main(argc, argv)
    int argc;
    char **argv;
{
    struct timeval total_timeout;
    register CLIENT *client;
    enum clnt_stat clnt_stat;
    char buf[1000], *s = buf;
 
    if ((client = clnt_create( argv[1], WINDOWPROG, WINDOWVERS,
                    "circuit_v")) == (CLIENT *) NULL) {
        clnt_pcreateerror("clnt_create");
        exit(1);
    }
    timerclear(&total_timeout);
    while (scanf("%s", s) != EOF)
        clnt_call(client, RENDERSTRING_BATCHED, xdr_wrapstring,
                   &s, xdr_void, (caddr_t) NULL, total_timeout);
    /* Now flush the pipeline */
    total_timeout.tv_sec = 20;
    clnt_stat = clnt_call(client, NULLPROC, xdr_void,
             (caddr_t) NULL, xdr_void, (caddr_t) NULL, total_timeout);
    if (clnt_stat != RPC_SUCCESS) {
        clnt_perror(client, "rpc");
        exit(1);
    }
    clnt_destroy(client);
    exit(0);
}

The following code example shows the dispatch portion of the batched server. Because the server sends no message, the clients are not notified of failures.

Example 5-6 Batched Server

#include <stdio.h>
#include <rpc/rpc.h>
#include "windows.h"
 
void
windowdispatch(rqstp, transp)
    struct svc_req *rqstp;
    SVCXPRT *transp;
{
    char    *s = NULL;
 
    switch(rqstp->rq_proc) {
        case NULLPROC:
            if (!svc_sendreply( transp, xdr_void, NULL))
                fprintf(stderr, "can't reply to RPC call\n");
            return;
        case RENDERSTRING:
            if (!svc_getargs( transp, xdr_wrapstring, &s)) {
                fprintf(stderr, "can't decode arguments\n");
                /* Tell caller an error occurred */
                svcerr_decode(transp);
                break;
            }
            /* Code here to render the string s */
            if (!svc_sendreply( transp, xdr_void, (caddr_t) NULL))
                fprintf( stderr, "can't reply to RPC call\n");
            break;
        case RENDERSTRING_BATCHED:
            if (!svc_getargs(transp, xdr_wrapstring, &s)) {
                fprintf(stderr, "can't decode arguments\n");
                /* Be silent in the face of protocol errors */
                break;
            }
            /* Code here to render string s, but send no reply! */
            break;
        default:
            svcerr_noproc(transp);
            return;
    }
    /* Now free string allocated while decoding arguments */
    svc_freeargs(transp, xdr_wrapstring, &s);
}

Note - To illustrate the benefits of batching, Example 5-4 and Example 5-6 were completed to render the lines in a 25,144-line file. The rendering service throws away the lines. The batched version of the application is four times as fast as the unbatched version.