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

6.  Porting From TS-RPC to TI-RPC

7.  Multithreaded RPC Programming

8.  Extensions to the Oracle Solaris RPC Library

A.  XDR Technical Note

What Is XDR?

Canonical Standard

XDR Library

XDR Library Primitives

Memory Requirements for XDR Routines

Number Filters

Floating-Point Filters

Enumeration Filters

No-Data Routine

Constructed Data Type Filters

Strings

Byte Arrays

Arrays

Array Example 1

Array Example 2

Array Example 3

Opaque Data

Fixed-Length Arrays

Discriminated Unions

Discriminated Union Example

Pointers

Pointer Example

Pointer Semantics

Nonfilter Primitives

Operation Directions

Stream Access

Standard I/O Streams

Memory Streams

Record TCP/IP Streams

XDR Stream Implementation

XDR Object

Advanced XDR Topics

Linked Lists

B.  RPC Protocol and Language Specification

C.  XDR Protocol Specification

D.  RPC Code Examples

E.  portmap Utility

Glossary

Index

What Is XDR?

XDR is the backbone of the Oracle Remote Procedure Call package. Data for RPCs are transmitted using this standard. XDR library routines should be used to transmit data accessed (read or written) by more than one type of machine.

XDR works across different languages, operating systems, and machine architectures. Most users (particularly RPC users) only need the information in the sections on number filters, floating point filters, and enumeration filters. Programmers who want to implement RPC and XDR on new machines should read this technical note and the protocol specification.

You can use rpcgen to write XDR routines even in cases where no RPC calls are being made.

C programs that use XDR routines must include the file <rpc/xdr.h>, which contains all the necessary interfaces to the XDR system. Because the library libnsl.a contains all the XDR routines, you compile it by typing:

example% cc program.c

In many environments, several criteria must be observed to accomplish porting. The ramifications of a small programmatic change are not always apparent, but they can often have far-reaching implications. Consider the program to read/write a line of text that is shown in the next two code examples.

Example A-1 Writer Example (initial)

#include <stdio.h>
 
main()             /* writer.c */
{     int i;
 
for (i = 0; i < 8; i++) {
         if (fwrite((char *) &i, sizeof(i), 1, stdout) != 1) {
             fprintf(stderr, "failed!\n");
             exit(1);
         }
     }
     exit(0);
}

Example A-2 Reader Example (initial)

#include <stdio.h>
 
main()       /* reader.c */
{
     int i, j;
 
    for (j = 0; j < 8; j++) {
         if (fread((char *) &i, sizeof(i), 1, stdin) != 1) {
             fprintf(stderr, "failed!\n");
             exit(1);
         }
         printf("%ld ", i);
     }
     printf("\n");
     exit(0);
}

The two programs appear to be portable because they:

Piping the output of the writer program to the reader program gives identical results on a SPARC or Intel machine.

% writer | reader
0 1 2 3 4 5 6 7
%
intel% writer | reader
0 1 2 3 4 5 6 7
intel%

With the advent of local area networks and 4.2BSD came the concept of “network pipes,” which is a process that produces data on one machine and a second process that consumes data on another machine. You can construct a network pipe with writer and reader. Here are the results if the writer produces data on a SPARC system, and the reader consumes data on Intel architecture.

% writer | rsh intel reader
0 16777216 33554432 50331648 67108864 83886080 100663296
117440512
%

Executing writer on the Intel and reader on the SPARC system produces identical results. These results occur because the byte ordering of data differs between the Intel and the SPARC, even though the word size is the same.


Note - 16777216 is 224. When 4 bytes are reversed, the 1 is placed in the 24th bit.


Whenever data is shared by two or more machine types, a need exists for portable data. You can make data portable by replacing the read() and write() calls with calls to an XDR library routine, xdr_int(), a filter that knows the standard representation of an int integer in its external form. The revised versions of writer are shown in the following code example.

Example A-3 Writer Example (XDR modified)

#include <stdio.h>

#include <rpc/rpc.h>    /* xdr is a sub-library of rpc */
 
main()       /* writer.c */
{
     XDR xdrs;
     int i;
 
xdrstdio_create(&xdrs, stdout, XDR_ENCODE);

     for (i = 0; i < 8; i++) {
         if (!xdr_int(&xdrs, &i)) {
             fprintf(stderr, "failed!\n");
             exit(1);
         }
     }
     exit(0);
}

The following code example shows the revised versions of reader.

Example A-4 Reader Example (XDR modified)

#include <stdio.h>

#include <rpc/rpc.h>    /* xdr is a sub-library of rpc */
 
main()                /* reader.c */
{
     XDR xdrs;
     int i, j;
 
xdrstdio_create(&xdrs, stdin, XDR_DECODE);

     for (j = 0; j < 8; j++) {
         if (!xdr_int(&xdrs, &i)) {
             fprintf(stderr, "failed!\n");
             exit(1);
         }
         printf("%ld ", i);
     }
     printf("\n");
     exit(0);
}

The new programs were executed on a SPARC system, on an Intel, and from a SPARC to an Intel. The results follow.

% writer | reader
0 1 2 3 4 5 6 7
%
intel% writer | reader
0 1 2 3 4 5 6 7
intel%
% writer | rsh intel reader
0 1 2 3 4 5 6 7
%

Note - Arbitrary data structures can create portability issues, particularly with respect to alignment and pointers. Alignment on word boundaries cause the size of a structure to vary from machine to machine. Pointers, which are very convenient to use, have no meaning outside the machine where they are defined.