Distinct ONC RPC/XDR for .NET Toolkit
Programming Guide

Documentation Roadmap

The Distinct ONC RPC/XDR Documentation is comprised of a:

·         Programming Guide: the current document. It provides a description of what this toolkit offers and provides information on how the components work and who should use it.

·         Quick Start for the RPC Novice: this is intended for users who are not experienced RPC programmers and wish to get a head start in integrating RPC into their application

·         Programmer’s Reference: this provides the syntax and description of all RPC and XDR API calls for the Distinct ONC RPC/XDR libraries. Note that the syntax in this reference marked as Visual C++ is for the C++/CLR language.

1. Introduction
This introduction is addressed to programmers who wish to write their own distributed applications in .NET using the Distinct® ONC RPC/XDR Toolkit for .NET.  The following are provided: 

·         A short description of the components of the Distinct ONC RPC/XDR for .NET Toolkit.

·         Step by step instructions how to build an RPC client application in .NET. First, the XDR interface definition file and the source code of the server in C are described. Then the required steps to build a .NET client are detailed resulting in a complete client application

·         The RPCGen.NET utility which compiles XDR Interface Definition files (.x) into C# client and server stubs.

·         Step by step instructions how to build an RPC server application in .NET. The required steps to build a .NET server are described resulting in a complete server application. The use of the ONC RPCBIND is also discussed.

·         How to restrict the range of ports that a server will listen on.

·         A listing of mapping between ONC XDR data types and .NET data types.

·         A section on how to use Distinct® ONC RPC/XDR Toolkit for .NET from Visual Basic .NET

·         A section on how to use Distinct® ONC RPC/XDR Toolkit for .NET from C++/CLR.

·         Several important RPC programming concepts are discussed in the last section. These concepts include authentication, making broadcast RPCs, batching RPCs, using XDR streamstimeout handling, error handling if required, and how to establish client and server connections through a firewall explains the use of fixed ports

·         A summary of issues to be aware of when upgrading from a previous version of Distinct ONC RPC/XDR for .NET.

This document assumes that you are already familiar with .NET, the basic concepts of RPC client/server computing and ONC RPC and XDR in particular. It also assumes a familiarity with the basics of the C binding of ONC RPC. If you wish to write .NET ONC RPC applications and are not yet familiar with these concepts you should start with the Quick Start for the RPC Novice guide and do further reading before using the toolkit. 

You may need to refer to the reference part of this manual to understand parts of the examples given in this programming guide. 

This toolkit may be used to help you out in several different scenarios. Here are some: 

·         Whenever you wish to write an ONC RPC client in any .NET-language to communicate with existing ONC RPC/XDR servers.

·         Whenever you wish to preserve the existing interface of an application written using the XDR specifications.

·         Whenever you wish to write C# code that can read and write XDR streams. Other (for example C, C++ ) applications often use this platform independent encoding format for serializing data. 

·         Whenever you wish to write simple client/server applications in .NET. 

In all these scenarios Distinct ONC RPC/XDR for .NET will certainly help you to write portable, high-quality C# code in a minimum amount of time that can be used from any .NET-language. 

This guide discusses how to write client/server applications using the Distinct ONC RPC/XDR Toolkit for .NET. It first explains how to write an ONC RPC client and then illustrates how a server is built in .NET.  It then describes some more advanced features, the understanding of which is fundamental to using this toolkit. It also includes a section on how to pass RPCs through Internet or Intranet firewalls.

2. What comes with the Distinct ONC RPC/XDR for .NET Toolkit? 
The Distinct ONC RPC/XDR Toolkit for .NET is a set of tools and libraries that enables you to write pure .NET ONC RPC clients and servers.
It consists of: 

·         The Distinct ONC RPC/XDR for .NET assembly that contains the ONC RPC/XDR run time libraries that conform to RFC 1831 (RPC: Remote Procedure Call Protocol Specification Version 2) and RFC 1832 (XDR: External Data Representation Standard). The API consists of classes that allow you to write .NET clients, for standard RPC servers, which can be embedded in applets and be run by a standard Web browser. It also allows you to develop ONC RPC stand-alone servers. The package allows connections over TCP and UDP. 

·         An RPCBIND application that implements the RPCBIND protocol versions 2 (portmapper), 3 and 4. 

·         The RPCGen.NET compiler that translates standard RPC/XDR interface definition files into C# classes that implement the client and server side stubs and the XDR conversion routines for the described interface. This means RPCGen.NET implements a C# language mapping for .x IDL files.

·         The RPCInfo utility displays a list of all the services registered with the RPCBIND on a system. This utility can be used to query the RPCBIND on the local host (by specifying "localhost") or on a remote host (by specifying the name or IP address of the host). Source code for the RPCInfo utility is included for reference. 

·         A set of demo applications that consist of an XDR file which describes an interface of a very simple server, the server implementation, and demo applications that invokes the server written in both Visual Basic.NET and C#.

3. Building a Client with Distinct ONC RPC/XDR for .NET
I
n this section we will illustrate how to use this toolkit to build a .NET client in C#. For our example we will use the scenario of an application programmer who wants to write a .NET-based front end for an existing ONC RPC service. 

When writing an ONC RPC application the first thing to do is to write an XDR interface definition (IDL) file. If you need to write an RPC client for an existing server you should obtain the XDR file for that server first. The IDL file describes the data types and the signature of your interface. Distinct ONC RPC/XDR for .NET understands the XDR language as described in RFC 1832 (XDR: External Data Representation Standard) and many of the extensions that have been added by various vendors over the last decade (like multiple arguments in one procedure and "in"/"out"/"inout" parameters). By common programming convention IDL files have a .x extension and are commonly referred to as .x files. 

3.1. The XDR Interface Definition Language File
For the remainder of this guide we will work with the XDR interface definition language (IDL) file demo.x as shown below. It defines a simple service that returns a sequence of consecutive lines from a text: 

%/*****************************************
% * Distinct ONC RPC/XDR for .NET Example *
% ****************************************/
 
struct request {
        int from;
        int to;
};
 
struct result {
        int number;
        string line<>;
        struct result *next;
};
 
typedef result *res_list;
 
program DEMO_SERVER {
        version DEMO_VERSION {
               res_list get_line(request) = 1;
        } = 1;
} = 0x20000023;
 
This IDL file has 5 sections: 
1.       A comment with leading '%' characters.
2.       A struct request type declaration. 
3.       A struct result type declaration. 
4.       A typedef res_list type declaration.
5.       A program definition for the server interface DEMO_SERVER.

The program definition contains only one procedure (function get_line()). It was a limitation of the original ONC RPC that each procedure may have only one input parameter and one return value. But as these parameters may be of arbitrary complex type (e.g. a structure), the restriction is only a syntactical one (with Distinct ONC RPC/XDR for .NET this limitation is gone and you can also specify multiple arguments per procedure like you would do in C). In our example the input type of get_line() (named request) contains two integers specifying a range of lines (named from and to). The output type res_list is a pointer to a linked list of result structures. Each element of this list describes one line of the result (line number and content string). In this example it is important to define the typedef result because with RPCGen.NET a procedure can have only plain type names in its signature (e.g. result *get_line(request) is not allowed). However since you can use any level of typedefs this is not really a semantic restriction.

3.2 The Server Implementation in C 
Although the functionality of the service might be obvious at this point, we show here its implementation in C to clarify any questions you may have. In this simple version the lines of text that can be returned are hard coded and there is no error processing done (e.g. if a client requests a non-existing range of lines). 

#include <stdio.h> 
#include <rpc/rpc.h> 
#include "demo.h" 
 
char *text[] = { 
        "This is the first line of text.", 
        "This is the second line of text.", 
        "This is the third line.", 
        "This is the 4th line.", 
        "This is the 5th line.", 
        "This is the 6th line.", 
        "This is the 7th line.", 
        "This is the 8th line." 
}; 
 
res_list *get_line_1(request *req) 
        static res_list rl; 
        result *p, *q; 
        result **n; 
        int c; 
 
        /* free any dynamically allocated memory from previous requests */ 
        p = rl; 
        while (p != NULL) { 
               q = p; 
               p = p->next; 
               free(q); 
        
 
        /* the handling of the new request starts here*/ 
        rl = NULL; 
 
        /* n points to the pointer where the next list element is inserted */ 
        n = &rl; 
        for (c = req->from - 1; c < req->to; c++) { 
               /* allocate the next element of the list */ 
               *n = malloc(sizeof(result)); 
 
               /* assign the line number */ 
               (*n)->number = c + 1; 
 
               /* assign the line (string) */ 
               (*n)->line = text[c]; 
               n = &((*n)->next); 
               *n = NULL; 
        
        return &rl; 

To build the server binary with just the demo.x IDL file and the demo_server.c file above, run the standard ONC RPC rpcgen (for C) on demo.x and compile and link the generated files demo_svc.c, demo_xdr.c, demo.h, and demo_server.c into one native binary. 

Once you have built the above server and have it up and running with the ONC RPC RPCBIND, you can proceed to build a .NET stand-alone client that calls this server. 

3.3 The .NET Client 
This section will take you through the steps needed to build the .NET client. The first thing to do is to run the RPCGen.NET provided with the Distinct ONC RPC/XDR for .NET Toolkit on the IDL file. The RPCGen.NET application translates XDR files into .NET stubs. For a complete description of the RPCGen.NET command see the section on RPCGen.NET.

You run RPCGen.NET on demo.x by typing: 

>RPCGen.NET –n demo.x 
RPCGen.NET V2.0, Copyright 1997 - 2009 by Distinct Corporation
writing: request.cs
writing: result.cs
writing: res_list.cs
writing: demoClient_vers1.cs


The execution of RPCGen.NET creates four .NET classes in four files, that implement the client stub for calling the demo service described. There is one file per type definition for request.cs, result.cs, and res_list.cs, and one main stub file called demoClient_vers1.cs. 

3.3.1 The Main Stub
We will now take a look at the demoClient_vers1.cs main stub file that has been generated. 

/*****************************************

 * Distinct ONC RPC/XDR for .NET Example *

 ****************************************/

 

using com.distinct.rpc;

 

namespace demoRPC {

 

/// <summary>

/// This class was automatically generated by Rpcgen.NET from the RPC/XDR file "demo.x"  .

/// It defines the client interface to a server implementing version 1 of the "DEMO_SERVER" program.

/// </summary>

public class demoClient_vers1 : NetRPCClient {

 

/// <summary> Program ID. </summary>

public const int DEMO_SERVER = 0x20000023;

 

/// <summary>

/// Creates and connects an RPC client for a server that implements version 1 of the "DEMO_SERVER" program.

/// Calls the remote Portmapper in order to get the port of the server. </summary>

/// <param name = "host"> The host on which the server resides. </param>

/// <param name = "stream"> true for a TCP connection, false for UDP. </param>

 

public demoClient_vers1(System.Net.IPAddress host, bool stream) :

  base(host, DEMO_SERVER, DEMO_VERSION, stream) { }

 

/// <summary>

/// Creates and connects an RPC client for a server that implements version 1 of the "DEMO_SERVER" program.

/// The client will try to connect to the specified server port. (No interaction with a portmapper) </summary>

/// <param name = "host"> The host on which the server resides. </param>

/// <param name = "port"> The port on which the server listens. </param>

/// <param name = "stream"> true for a TCP connection, false for UDP. </param>

 

public demoClient_vers1(System.Net.IPAddress host, int port, bool stream) :

  base(host, DEMO_SERVER, DEMO_VERSION, port, stream) { }

 

/// <summary>

/// Creates an RPC client for a server that implements version 1 of the "DEMO_SERVER"  program.

/// The client is initialized with an externally created protocol client object. </summary>

/// <param name = "protocol"> The protocol object that implements the client connection. </param>

 

public demoClient_vers1(ClientGeneric protocol) :

  base(protocol) { }

 

/// <summary> Version ID of the program. </summary>

public const int DEMO_VERSION = 1;

 

/// <summary> Procedure number of get_line </summary>

public const int get_line = 1;

 

/// <summary>

/// Stub method that invokes the server function "get_line" (version 1). </summary>

/// <param name = "arg1"> input parameter of the RPC. </param>

/// <returns> The return value of the RPC. </returns>

 

public res_list get_line_1(request arg1) {

 

  res_list retval = new res_list();

  GetClient().Call(get_line, arg1, retval);

 

  return retval;

}

}

}

An instance of this demo stub class represents a client to the demo server. It maintains the complete necessary connection status. Without going into all details we can easily see that this class consists of a number of constants, three constructors, and a public method get_line_1() that has the same signature as get_line() in the XDR f