The following is an example of the lowest layer of RPC on the client side program:
#define RMTPROGNUM (u_long)0x3fffffffL
#define RMTPROGVER (u_long)0x1L
#define STRINGPROC (u_long)2
#include <stdio.h>
#include <rpc\rpc.h>
#include <sys\socket.h>
#include <netdb.h>
main(argc, argv)
int argc;
char *argv[ ];
{
struct hostent *hp;
struct timeval pertry_timeout, total_timeout;
struct sockaddr_in server_addr;
int sock = RPC_ANYSOCK;
static char buf[100], *strc_in= "Hello", *strc_out=buf;
char *parrc_in, *parrc_out;
register CLIENT *clnt;
enum clnt_stat cs;
...
/* get the Internet address of RPC server host */
if ((hp = gethostbyname("RPCSERVER_HOST")) == NULL)
{
fprintf(stderr,"Can't get address for %s\n","RPCSERVER_HOST");
exit (-1);
}
pertry_timeout.tv_sec = 3;
pertry_timeout.tv_usec = 0;
/* set sockaddr_in structure */
bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr.s_addr,
hp->h_length);
server_addr.sin_family = AF_INET;
server_addr.sin_port = 0;
/* create clnt TCP handle */
if ((clnt = clnttcp_create(&server_addr, RMTPROGNUM, RMTPROGVER,
&sock, 1024*10, 1024*10)) == NULL)
{
clnt_pcreateerror("clnttcp_create fail"); /* Why failed ? */
exit(-1);
}
/*
* create clnt UDP handle
* if ((clnt = clntudp_create(&server_addr, RMTPROGNUM, RMTPROGVER,
* pertry_timeout, &sock)) == NULL)
* {
* clnt_pcreateerror("clntudp_create fail");
* exit(-1);
* }
*/
total_timeout.tv_sec = 10;
total_timeout.tv_usec = 0;
...
/*call the remote procedure STRINGPROC associated with */
/*client handle (clnt) */
cs=clnt_call(clnt, STRINGPROC,xdr_wrapstring,
(char *)&strc_in[j],
xdr_wrapstring, (char *)&strc_out,total_timeout);
if (cs != RPC_SUCCESS)
printf("*Error* clnt_call fail :\n");
clnt_destroy(clnt); /* deallocate any memory associated */
/* with clnt handle */
...
}
The following steps describe the lowest layer of RPC on the client side program:
Use the gethostbyname() call to determine the internet address of the host, which is running the RPC server. Initialize the socaddr_in structure, found in the <NETINET\IN.H> header file.
If you are not familiar with socket calls, see Sockets General Programming Information.
The clnttcp_create() and clntudp_create() calls create TCP and UDP client RPC handles (CLIENT), respectively. The CLIENT structure is defined in the <RPC\CLNT.H> header file.
There are six parameters for the clnttcp_create() call:
The low-level version of the callrpc() call is the clnt_call(), which has seven parameters:
The return code RPC_SUCCESS indicates a successful call; otherwise, an error has occurred. You find the RPC error code in the <RPC\CLNT.H> header file.
The clnt_destroy() call always deallocates the space associated with the client handle. If the RPC library opened the socket associated with the client handle, the clnt_destroy() call closes it. If you open the socket, it stays open.