Extensions to the Sun RPC Library
New features have been added to the Sun RPC library which are integrated into the standard Solaris 9 product.
New and altered man pages are available to describe the functionality added to the Sun RPC library.
The additions to the Sun RPC library are described in the following sections:
New Features
The new features added to the Sun RPC library are:
One-way messaging - Reduces the time a client thread waits before continuing processing.
Non-blocking I/O - Enables a client to send requests without being blocked.
Client connection closure callback - Enables a server to detect client disconnection and to take corrective action.
Callback user file descriptor - Extends the RPC server to handle non-RPC descriptors.
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
In previous versions of the Sun 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
Previous versions of the Sun 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 Sun RPC library, and the oneway attribute has been added to the RPC grammar.
clnt_send()
In previous versions of the Sun 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:
Use a simplified interface as outlined in the Chapter 2, 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(3NSL) 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 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.
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.
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.
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.
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.
To launch the server that you built, type ./server
Finally, to invoke the service in another shell, type: ./client servername23.
23 is the number being added to the global counter.