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

New Features

One-Way Messaging

clnt_send()

oneway Attribute

One-way call using a simple counter service

Non-Blocking I/O

Using Non-Blocking I/O

Using a simple counter with non-blocking I/O

clnt_call() Configured as Non-Blocking

Client Connection Closure Callback

Example of client connection closure callback

User File Descriptor Callbacks

Example of User File Descriptors

A.  XDR Technical Note

B.  RPC Protocol and Language Specification

C.  XDR Protocol Specification

D.  RPC Code Examples

E.  portmap Utility

Glossary

Index

One-Way Messaging

In one-way messaging the client thread sends a request containing a message to the server. The client thread does not wait for a reply from the server and is free to continue processing when the request has been accepted by the transport layer. The request is not always sent immediately to the server by the transport layer, but waits in a queue until the transport layer sends it. The server executes the request received by processing the message contained in the request. This method saves processing time.

The following figure illustrates one-way messaging.

Figure 8-1 One-Way Messaging

image:Text describes graphic.

In previous versions of the Oracle Solaris RPC library, most requests were sent by two-way messaging. In two-way messaging, the client thread waits until it gets an answer from the server before continuing processing. If the client thread does not receive a reply from the server within a certain period of time, a time-out occurs. This client thread cannot send a second request until the first request is executed or until a time-out occurs. This messaging method is illustrated in the following figure.

Figure 8-2 Two-Way Messaging

image:Text describes graphic.

Previous versions of the Oracle Solaris RPC library contain a second method of messaging called batching. In this method, client request are held in a queue until a group of requests can be processed at the same time. This is a form of one-way messaging. See Chapter 4, Programmer's Interface to RPC for further details.

After the transport layer accepts a request, the client is not notified of failures in transmission and does not receive a receipt from the server from the request. For example, if the server refuses the request due to an authentication problem, the client is not notified of this problem. If the transport layer does not accept the request, the sending operation returns an immediate error to the client.

If you need to check whether the server is functioning correctly, you can send a two-way request to the server. Such a request can determine whether the server is still available and whether it has received the one-way requests sent by the client.

For one-way messaging, the clnt_send() function has been added to the Oracle Solaris RPC library, and the oneway attribute has been added to the RPC grammar.

clnt_send()

In previous versions of the Oracle Solaris RPC library, you used the clnt_call() function to send a remote procedure call. With the extended one-way messaging service, the clnt_send() function sends one-way remote procedure calls.

When the client calls clnt_send(), the client sends a request to the server and continues processing. When the request arrives at the server, the server calls a dispatch routine to process the incoming request.

Like clnt_call(), the clnt_send() function uses a client handle to access a service. See the clnt_send(3NSL) and clnt_call(3NSL) man pages for further information.

If you do not provide the correct version number to clnt_create(), clnt_call() fails. In the same circumstances, clnt_send() does not report the failure, as the server does not return a status.

oneway Attribute

To use one-way messaging, add the oneway keyword to the XDR definition of a server function. When you use the oneway keyword, the stubs generated by rpcgen use clnt_send(). You can either:

For one-way messaging, use version 1.1 of the rpcgen command.

When declaring the oneway keyword, follow the RPC language specification using the following syntax:

"oneway" function-ident "(" type-ident-list ")" "=" value;

See Appendix B, RPC Protocol and Language Specification for details on RPC language specifications.

When you declare the oneway attribute for an operation, no result is created on the server side and no message is returned to the client.

The following information on the oneway attribute must be added to the RPC Language Definition Table as described in RPC Language Specification:

type-ident procedure-ident (type-ident) = value
oneway procedure-ident (type-ident) = value

One-way call using a simple counter service

This section describes how to use a one-way procedure on a simple counter service. In this counter service the ADD() function is the only function available. Each remote call sends an integer and this integer is added to a global counter managed by the server. For this service, you must declare the oneway attribute in the RPC language definition.

In this example, you generate stubs using the -M, -N and -C rpcgen options. These options ensure that the stubs are multithread safe, accept multiple input parameters and that generated headers are ANSI C++ compatible. Use these rpcgen options even if the client and server applications are mono-threaded as the semantic to pass arguments is clearer and adding threads in applications is easier since the stubs do not change.

  1. First, you write the service description in the counter.x.

       /* counter.x: Remote counter protocol */
    program COUNTERPROG {
         version COUNTERVERS {
           oneway ADD(int) = 1;
         } = 1;
    } = 0x20000001;

    The service has a program number, (COUNTERPROG) 0x200000001, and a version number, (COUNTERVERS) 1.

  2. Next, call rpcgen on the counter.x file.

    rpcgen -M -N -C counter.x

    This call generates the client and server stubs, counter.h, counter_clnt.c and counter_svc.c.

  3. As shown in the server.c file below, write the service handler for the server side and the counterprog_1_freeresult() function used to free memory areas allocated to the handler. The RPC library calls this function when the server sends a reply to the client.

          #include <stdio.h>
    #include "counter.h"
    
    int counter = 0;
    
           bool_t
    add_1_svc(int number, struct svc_req *rqstp)
    {
          bool_t retval = TRUE;
    
           counter = counter + number;
    
           return retval;
    }
          int
    counterprog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t
                             result)
    {
          (void) xdr_free(xdr_result, result);
    
           /*
              * Insert additional freeing code here, if needed 
              */
    
           return TRUE;
    }

    You build the server by compiling and linking the service handler to the counter_svc.c stub. This stub contains information on the initialization and handling of TI-RPC.

  4. Next, you write the client application, client.c.

          #include <stdio.h>
    #include "counter.h"
    
    main(int argc, char *argv[])
    {
          CLIENT *clnt;
          enum clnt_stat result;
          char *server;
          int number;
    
           if(argc !=3) {
               fprintf(stderr, "usage: %s server_name number\n", argv[0];
                  exit(1);
              }
          server = argv[1];
          number = atoi(argv[2]);
    
           /* 
              * Create client handle 
              */
          clnt = clnt_create(server, COUNTERPROG, COUNTERVERS, "tcp");
    
           if(clnt == (CLIENT *)NULL) {
             /* 
              * Couldn't establish connection 
              */
                   clnt_pcreateerror(server);
               exit(1);
          }
    
           result = add_1(number, clnt);
          if (result !=RPC_SUCCESS) {
               clnt_perror(clnt, "call failed");
          }
    
           clnt_destroy(clnt);
          exit(0); 
    }

    The add_1() client function is the counter_clnt.c stub generated for the remote function.

    To build the client, compile and link the client main and the counter_clnt.c.

  5. To launch the server that you built, type ./server

  6. Finally, to invoke the service in another shell, type: ./client servername23.

    23 is the number being added to the global counter.