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(); } |