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

Simplified Interface

Client Side of Simplified Interface

Server Side of the Simplified Interface

Hand-Coded Registration Routine

Passing Arbitrary Data Types

Standard Interfaces

Top-Level Interface

Client Side of the Top-Level Interface

Intermediate-Level Interface

Client Side of the Intermediate-Level Interface

Server Side of the Intermediate-Level Interface

Expert-Level Interface

Client Side of the Expert-Level Interface

Server Side of the Expert-Level Interface

Bottom-Level Interface

Client Side of the Bottom-Level Interface

Server Side of the Bottom-Level Interface

Server Caching

Low-Level Data Structures

Testing Programs Using Low-Level Raw RPC

Connection-Oriented Transports

Memory Allocation With XDR

5.  Advanced RPC Programming Techniques

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

Connection-Oriented Transports

Example 4-20 copies a file from one host to another. The RPC send() call reads standard input and sends the data to the server receive(), which writes the data to standard output. This example also illustrates an XDR procedure that behaves differently on serialization and on deserialization. A connection-oriented transport is used.

Example 4-20 Remote Copy (Two-Way XDR Routine)

/*
 * The xdr routine:
 *      on decode, read wire, write to fp
 *      on encode, read fp, write to wire
 */
#include <stdio.h>
#include <rpc/rpc.h>
 
bool_t
xdr_rcp(xdrs, fp)
    XDR *xdrs;
    FILE *fp;
{
    unsigned long size;
    char buf[BUFSIZ], *p;
 
    if (xdrs->x_op == XDR_FREE)            /* nothing to free */
        return(TRUE);
    while (TRUE) {
        if (xdrs->x_op == XDR_ENCODE) {
            if ((size = fread( buf, sizeof( char ), BUFSIZ, fp))
                   == 0 && ferror(fp)) {
                fprintf(stderr, "can't fread\n");
                return(FALSE);
            } else
                return(TRUE);
        }
        p = buf;
        if (! xdr_bytes( xdrs, &p, &size, BUFSIZ))
            return(0);
        if (size == 0)
            return(1);
        if (xdrs->x_op == XDR_DECODE) {
            if (fwrite( buf, sizeof(char), size, fp) != size) {
                fprintf(stderr, "can't fwrite\n");
                return(FALSE);
            } else
                return(TRUE);
        }
    }
}

In Example 4-21 and Example 4-22, the serializing and deserializing are done only by the xdr_rcp() routine shown in Example 4-20.

Example 4-21 Remote Copy Client Routines

/* The sender routines */
#include <stdio.h>

#include <netdb.h>
#include <rpc/rpc.h>

#include <sys/socket.h>
#include <sys/time.h>
#include "rcp.h"
 
main(argc, argv)
    int argc;
    char **argv;
{
    int xdr_rcp();
 
    if (argc != 2 7) {
        fprintf(stderr, "usage: %s servername\n", argv[0]);
        exit(1);
    }
    if( callcots( argv[1], RCPPROG, RCPPROC, RCPVERS, xdr_rcp,
stdin,
          xdr_void, 0 ) != 0 )
        exit(1);
    exit(0);
}
 
callcots(host, prognum, procnum, versnum, inproc, in, outproc,
out)
    char *host, *in, *out;
    xdrproc_t inproc, outproc;
{
    enum clnt_stat clnt_stat;
    register CLIENT *client;
    struct timeval total_timeout;
 
    if ((client = clnt_create( host, prognum, versnum,
"circuit_v")
       == (CLIENT *) NULL)) {
        clnt_pcreateerror("clnt_create");
        return(-1);
    }
    total_timeout.tv_sec = 20;
    total_timeout.tv_usec = 0;
    clnt_stat = clnt_call(client, procnum, inproc, in, outproc,
out,
                           total_timeout);
    clnt_destroy(client);
    if (clnt_stat != RPC_SUCCESS)
        clnt_perror("callcots");
    return((int)clnt_stat);
}

The following code example defines the receiving routines. Note that in the server, xdr_rcp() did all the work automatically.

Example 4-22 Remote Copy Server Routines

/*
 * The receiving routines
 */
#include <stdio.h>
#include <rpc/rpc.h
#include "rcp.h"
 
main()
{
    void  rcp_service();
    if (svc_create(rpc_service,RCPPROG,RCPVERS,"circuit_v") == 0) {
        fprintf(stderr, "svc_create: errpr\n");
        exit(1);
    }
    svc_run();                    /* never returns */
    fprintf(stderr, "svc_run should never return\n");
}
 
void
rcp_service(rqstp, transp)
    register struct svc_req *rqstp;
    register SVCXPRT *transp;
{
    switch(rqstp->rq_proc) {
        case NULLPROC:
            if (svc_sendreply(transp, xdr_void, (caddr_t) NULL)
                                    == FALSE)
                fprintf(stderr, "err: rcp_service");
            return;
        case RCPPROC:
            if (!svc_getargs( transp, xdr_rcp, stdout)) {
                svcerr_decode(transp);
                return();
            }
            if(!svc_sendreply(transp, xdr_void, (caddr_t) NULL)) {
                fprintf(stderr, "can't reply\n");
                return();
            }
            return();
        default:
            svcerr_noproc(transp);
            return();
    }
}