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 Example of User File Descriptors  Previous   Contents   Next 
   
 

The todServer.c file shows the use of the timeofday service from the server side.

   #include "timeofday.h"
#include "userfdServer.h"
#include <stdio.h>
#include <errno.h>
#define PORT_NUMBER 1971

int listenSocket;

/* 
 * Implementation of the RPC server. 
 */

    int*
sendtimeofday_1_svc(char* time, struct svc_req* req)
{
    static int result = 0;
    
    printf("Server: Receive local time from client  %s\n", time);
    return &result;
}
    
    char **
gettimeofday_1_svc(struct svc_req* req)
{
    static char buff[80];
    char* pts;
    time_t now;
    static char* result = &(buff[0]);

    time(&now);
    strcpy(result, ctime(&now));

    return &result;
}

/* 
	 * Implementation of the socket server. 
 */

    int
create_connection_socket()
{
    struct sockaddr_in sin;
    int size = sizeof(struct sockaddr_in);
    unsigned int port;

		 /*
		  * Create a socket
		  */
    listenSocket = socket(PF_INET, SOCK_STREAM, 0);

    if (-1 == listenSocket) {
        perror("cannot allocate socket.");
        return -1;
    }

    sin.sin_port = htons(PORT_NUMBER);
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;
    
    if (bind(listenSocket, (struct sockaddr*)&sin, sizeof(sin)) == -1) {
        perror("cannot bind the socket.");
        close(listenSocket);
        return -1;
    }
		 /*
		  * The server waits for the client 
		  * connection to be created
		  */
    if (listen(listenSocket, 1)) {
        perror("cannot listen.");
        close(listenSocket);
        listenSocket = -1;        
        return -1;
    }

		 /* 
		  * svc_add_input registers a read callback, 
		  * socket_new_connection, on the listening socket. 
		  * This callback is invoked when a new connection 
		  * is pending. */
    if (svc_add_input(listenSocket, POLLIN,
                      socket_new_connection, (void*) NULL) == -1) {
        puts("Cannot register callback");
        close(listenSocket);
        listenSocket = -1;        
        return -1;
    }
        
    return 0;
}

/*
 * Define the socket_new_connection callback function
 */
    void
socket_new_connection(svc_input_id_t id, int fd,
                      unsigned int events, void* cookie)
{
    Link* lnk;
    int connSocket;

		 /* 
		  * The server is called when a connection is 
		  * pending on the socket. Accept this connection now. 
		  * The call is non-blocking. 
		  * Create a socket to treat the call.
		  */
    connSocket = accept(listenSocket, NULL, NULL);
    if (-1 == connSocket) {
        perror("Server: Error: Cannot accept a connection.");
        return;
    }

    lnk = (Link*)malloc(sizeof(Link));
    lnk->in_data[0] = 0;
    
		 /*
		  * New callback created, socket_read_callback.
		  */
    lnk->in_id = svc_add_input(connSocket, POLLIN,
			       socket_read_callback, (void*)lnk);
}
/*
 * New callback, socket_read_callback, is defined
 */
    void
socket_read_callback(svc_input_id_t id, int fd, unsigned int events,
                     void* cookie)
{
    char buffer[128];
    int len;
    Link* lnk = (Link*)cookie;

    /* 
		  * Read the message. This read call does not block. 
		  */
    len = read(fd, buffer, sizeof(buffer));

    if (len > 0) {
    	  /* 
				* Got some data. Copy it in the buffer 
				* associated with this socket connection. 
				*/
        strncat (lnk->in_data, buffer, len);

        /* 
				* Test if we receive the complete data.
         * Otherwise, this is only a partial read. 
				*/
        if (buffer[len-1] == 0) {
            char* pts;
            time_t now;
            
            /* 
					 * Print the time of day you received. 
					 */
            printf("Server: Got time of day from the client: \n %s",
                   lnk->in_data);

            /* 
					 * Setup the reply data  
					 * (server current time of day). 
					 */
            time(&now);
            pts = ctime(&now);

            strcpy(lnk->out_data, pts);
            lnk->out_ptr = &(lnk->out_data[0]);

					/* 
					 * Register a write callback (socket_write_callback)
					 * that does not block when writing a reply. 
					 * You can use POLLOUT when you have write 
					 * access to the socket
					 */ 
            lnk->out_id = svc_add_input(fd, POLLOUT,
                                        socket_write_callback, (void*)lnk);

        }
    } else if (len == 0) {
    /* 
     * Socket closed in peer.  Closing the socket. 
     */
	close(fd);
    } else {
        /* 
				* Has the socket been closed by peer? 
				*/
        if (errno != ECONNRESET) {
            /* 
					 * If no, this is an error. 
					 */
            perror("Server: error in reading the socket");
            printf("%d\n", errno);
        }
        close(fd);
    }
}

/*
 * Define the socket_write_callback. 
 * This callback is called when you have write 
 * access to the socket. 
 */
    void
socket_write_callback(svc_input_id_t id, int fd, unsigned int events,
                      void* cookie)
{
    Link* lnk = (Link*)cookie;

    /* 
		  * Compute the length of remaining data to write. 
		  */
    int len = strlen(lnk->out_ptr)+1;

/*
 * Send the time to the client
 */
    if (write(fd, lnk->out_ptr, len) == len) {
    /* 
		  * All data sent. 
		  */

    	/* 
		  	 * Unregister the two callbacks. This unregistration
     	 * is demonstrated here as the registration is 
		  	 * removed automatically when the file descriptor 
			 * is closed.
			 */
        svc_remove_input(lnk->in_id);
        svc_remove_input(lnk->out_id);
        
        /* 
				* Close the socket. 
				*/
        close(fd);
    }
}

    void
main()
{
    int res;

		 /*
		  * Create the timeofday service and a socket
		  */
    res = create_connection_socket();
    if (-1 == res) {
        puts("server: unable to create the connection socket.\n");
        exit(-1);
    }
    
    res = svc_create(timeofday_1, TIMEOFDAY, VERS1, "tcp");
    if (-1 == res) {
        puts("server: unable to create RPC service.\n");
        exit(-1);
    }
    
		 /*
		  Poll the user file descriptors.
		  */
    svc_run();
}
 
 
 
  Previous   Contents   Next