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



