Go to main content

ONC+ RPC Developer's Guide

Exit Print View

Updated: November 2020

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 6  One-Way Messaging

image:Graphic illustrates one-way messaging

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 7  Two-Way Messaging

image:Graphic illustrates two-way messaging

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 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() Function

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(3C) and clnt_call(3C) 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:

  • Use a simplified interface as outlined in the Introduction to TI-RPC. The stubs used by the simplified interface must call clnt_send().

  • Call the clnt_send() function directly, as described in the clnt_send(3C) man page.

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 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 about 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. Write the service description in the counter.x file.

       /* 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. 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 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;
    add_1_svc(int number, struct svc_req *rqstp)
     	 bool_t retval = TRUE;
      	 counter = counter + number;
      	 return retval;
    counterprog_1_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t
     	 (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. 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];
     	 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 
      	 result = add_1(number, clnt);
     	 if (result !=RPC_SUCCESS) {
     		  clnt_perror(clnt, "call failed");

    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. To invoke the service in another shell, type: ./client servername23.

    23 is the number being added to the global counter.