ONC+ Developer's Guide

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:

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.