Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
8.  Extensions to the Sun RPC Library User File Descriptor Callbacks  Previous   Contents   Next 
   
 

Example of User File Descriptors

This example shows you how to register a user file descriptor on an RPC server and how to provide user defined callbacks. With this example you can monitor the time of day on both the server and the client.

The makefile for this example is shown below.

   RPCGEN = rpcgen

CLIENT = todClient
CLIENT_SRC = todClient.c timeofday_clnt.c 
CLIENT_OBJ = $(CLIENT_SRC:.c=.o) 

SERVER = todServer
SERVER_SRC = todServer.c timeofday_svc.c 
SERVER_OBJ = $(SERVER_SRC:.c=.o)

RPCGEN_FILES = timeofday_clnt.c timeofday_svc.c  timeofday.h

CFLAGS += -I.

RPCGEN_FLAGS = -N -C
LIBS = -lsocket -lnsl

all: ./$(CLIENT) ./$(SERVER)


$(CLIENT): timeofday.h $(CLIENT_OBJ)
			  cc -o $(CLIENT) $(LIBS) $(CLIENT_OBJ)  

$(SERVER): timeofday.h $(SERVER_OBJ) 
			  cc -o $(SERVER)  $(LIBS) $(SERVER_OBJ)  

timeofday_clnt.c: timeofday.x
		  	  $(RPCGEN) -l $(RPCGEN_FLAGS) timeofday.x > timeofday_clnt.c

timeofday_svc.c: timeofday.x
			  $(RPCGEN) -m $(RPCGEN_FLAGS) timeofday.x > timeofday_svc.c

timeofday.h: timeofday.x
			  $(RPCGEN) -h $(RPCGEN_FLAGS) timeofday.x > timeofday.h


clean:
			  rm -f $(CLIENT_OBJ) $(SERVER_OBJ) $(RPCGEN_FILES)

The timeofday.x file defines the RPC services offered by the server in this example. The services in this examples are gettimeofday() and settimeofday().

program TIMEOFDAY { 
			  version VERS1 {
					 	  int SENDTIMEOFDAY(string tod) = 1;

					 	  string GETTIMEOFDAY() = 2;
			  } = 1;
} = 0x20000090;

The userfdServer.h file defines the structure of messages sent on the sockets in this example.

   #include "timeofday.h"
#define PORT_NUMBER 1971

/* 
 * Structure used to store data for a connection. 
	 *	(user fds test). 
 */
typedef struct {
	/* 
 * Ids of the callback registration for this link. 
 */
    svc_input_id_t in_id;
    svc_input_id_t out_id;
    
    /* 
		  * Data read from this connection. 
		  */
    char in_data[128];
    
    /* 
		  * Data to be written on this connection. 
		  */
    char out_data[128];
    char* out_ptr;
    
} Link;

    void
socket_read_callback(svc_input_id_t id, int fd, unsigned int events,
								  void* cookie);
    void
socket_write_callback(svc_input_id_t id, int fd, unsigned int events,
                      void* cookie);
    void
socket_new_connection(svc_input_id_t id, int fd, unsigned int events,
                      void* cookie);

    void
timeofday_1(struct svc_req *rqstp, register SVCXPRT *transp);

The todClient.c file shows how the time of day is set on the client. In this file, RPC is used with and without sockets.

   #include "timeofday.h"

#include <stdio.h>
#include <netdb.h>
#define PORT_NUMBER 1971

    void
runClient();
    void
runSocketClient();


char* serv_addr;

    void
usage()
{
    puts("Usage: todClient [-socket] <server_addr>");
    exit(2);
}

    int
main(int argc, char* argv[])
{
    CLIENT* clnt;
    int sockClient;
    
    if ((argc != 2) && (argc != 3))
        usage();

    sockClient = (strcmp(argv[1], "-socket") == 0);

		/*
		 * Choose to use sockets (sockClient). 
		 * If sockets are not available,
		 * use RPC without sockets (runClient).
		 */
    if (sockClient && (argc != 3))
        usage();
    
    serv_addr = argv[sockClient? 2:1];

    if (sockClient) {
        runSocketClient();
    } else {
        runClient();
    }

    return 0;
}
/*
	 * Use RPC without sockets
 */
    void
runClient()
{
    CLIENT* clnt;
    char* pts;
    char** serverTime;
    
    time_t now;

    clnt = clnt_create(serv_addr, TIMEOFDAY, VERS1, "tcp");
    if (NULL == clnt) {
        clnt_pcreateerror("Cannot connect to log server");
        exit(1);
    }

    time(&now);
    pts = ctime(&now);

    printf("Send local time to server\n");
    
    /* 
		  * Set the local time and send this time to the server. 
		  */
    sendtimeofday_1(pts, clnt);

    /* 
		  * Ask the server for the current time. 
		  */
    serverTime = gettimeofday_1(clnt);

    printf("Time received from server: %s\n", *serverTime);
    
    clnt_destroy(clnt);
}

/*
 * Use RPC with sockets
 */
    void
runSocketClient()
/*
 * Create a socket
 */
{
    int s = socket(PF_INET, SOCK_STREAM, 0);
    struct sockaddr_in sin;
    char* pts;
    char buffer[80];
    int len;
    
    time_t now;
    struct hostent* hent;
    unsigned long serverAddr;

    if (-1 == s) {
        perror("cannot allocate socket.");
        return;
    }
    
    hent = gethostbyname(serv_addr);
    if (NULL == hent) {
        if ((int)(serverAddr = inet_addr(serv_addr)) == -1) {
            puts("Bad server address");
            return;
        }
    } else {
        memcpy(&serverAddr, hent->h_addr_list[0], sizeof(serverAddr));
    }

    sin.sin_port = htons(PORT_NUMBER);
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = serverAddr;

		 /*
		  * Connect the socket
		  */
    if (-1 == connect(s, (struct sockaddr*)(&sin),
                      sizeof(struct sockaddr_in))) {
        perror("cannot connect the socket.");
        return;
    }

    time(&now);
    pts = ctime(&now);

		/*
		 * Write a message on the socket. 
		 * The message is the current time of the client.
		 */
    puts("Send the local time to the server.");
    if (-1 == write(s, pts, strlen(pts)+1)) {
        perror("Cannot write the socket");
        return;
    }

		 /*
		  * Read the message on the socket. 
		  * The message is the current time of the server
		  */
    puts("Get the local time from the server.");
    len = read(s, buffer, sizeof(buffer));

    if (len == -1) {
        perror("Cannot read the socket");
        return;
    }
    puts(buffer);
    
    puts("Close the socket.");
    close(s);
}
 
 
 
  Previous   Contents   Next