The logClient.c file shows a client using the log server.
#include "log.h" #include <stdio.h> #define MSG_SIZE 128 void usage() { puts("Usage: logClient <logserver_addr>"); exit(2); } void runClient(CLIENT* clnt) { char msg[MSG_SIZE]; int logID; int* result; /* * client opens a log */ result = openlog_1("client", clnt); if (NULL == result) { clnt_perror(clnt, "openlog"); return; } logID = *result; if (-1 == logID) { puts("Cannot open the log."); return; } while(1) { struct rpc_err e; /* * Client writes a message in the log */ puts("Enter a message in the log (\".\" to quit):"); fgets(msg, MSG_SIZE, stdin); /* * Remove trailing CR */ msg[strlen(msg)-1] = 0; if (!strcmp(msg, ".")) break; if (writelog_1(logID, LOG_INFO, msg, clnt) == NULL) { clnt_perror(clnt, "writelog"); return; } } /* * Client closes the log */ result = closelog_1(logID, clnt); if (NULL == result) { clnt_perror(clnt, "closelog"); return; } logID = *result; if (-1 == logID) { puts("Cannot close the log."); return; } } int main(int argc, char* argv[]) { char* serv_addr; CLIENT* clnt; if (argc != 2) usage(); serv_addr = argv[1]; clnt = clnt_create(serv_addr, LOG, LOG_VERS1, "tcp"); if (NULL == clnt) { clnt_pcreateerror("Cannot connect to log server"); exit(1); } runClient(clnt); clnt_destroy(clnt); } |
User File Descriptor Callbacks
User file descriptor callbacks enable you to register file descriptors with callbacks, specifying one or more event types. Now you can use an RPC server to handle file descriptors that were not written for the Sun RPC library.
With previous versions of the Sun RPC library, you could use a server to receive both RPC calls and non-RPC file descriptors only if you wrote your own server loop, or used a separate thread to contact the socket API.
For user file descriptor callbacks, two new functions have been added to the Sun RPC library, svc_add_input(3NSL) and svc_remove_input(3NSL), to implement user file descriptor callbacks. These functions declare or remove a callback on a file descriptor.
When using this new callback feature you must:
Create your callback() function by writing user code with the following syntax:
typedef void (*svc_callback_t) (svc_input_id_t id, int fd, \ unsigned int revents, void* cookie);
The four parameters passed to the callback() function are:
id Provides an identifier for each callback. This identifier can be used to remove a callback.
fd The file descriptor that your callback is waiting for.
revents An unsigned integer representing the events that have occurred. This set of events is a subset of the list given when the callback is registered.
cookie The cookie given when the callback is registered. This cookie can be a pointer to specific data the server needs during the callback.
Call svc_add_input() to register file descriptors and associated events, such as read or write, that the server must be aware of.
A list of the events that can be specified is given inpoll(2) .svc_input_id_t svc_add_input (int fd, unsigned int revents, \ svc_callback_t callback, void* cookie);
Specify a file descriptor. This file descriptor can be an entity such as a socket or a file.
When you no longer need a particular callback, call svc_remove_input() with the corresponding identifier to remove the callback.