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
streams, timeout 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
In 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 |