As mentioned previously, in-process servers are a major enhancement in serverSK. Program 1 shows how to write a DLL to provide these services. Two familiar functions are shown, a word counting function and a toupper function.
Program 1. commandIP: Sample In-Process Servers
/* */ /* "In Process Server" commands to use with serverSK, etc.*/ /* */ /* There are several commands implemented as DLLs*/ /* Each command function must be a thread-safe function */ /* and take two parameters. The first is a string:*/ /* command arg1 arg2 ... argn (i.e.; a RESTRICTED command*/ /* line with no spaces or quotes in the command or args)*/ /* and the second is the file name for the output*/ /* The code is C, without decorated names*/
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h>
static void ExtractToken (int, char *, char *);
__declspec (dllexport) int __cdecl wcip (char * command, char * output_file) /* word count; in process (ONE FILE ONLY)*/ /* Count the number of characters, works, and lines in*/ /* the file specified as the second token in "command"*/ /* NOTE: Simple version; results may differ from wc utility*/ { FILE * fIn, *fOut; int ch, c, nl, nw, nc; char inputFile[256];
ExtractToken (1, command, inputFile);
fIn = fopen (inputFile, "r"); if (fIn == NULL) return 1;
ch = nw = nc = nl = 0; while ((c = fgetc (fIn)) != EOF) { if (c == '\0') break; if (isspace(c) && isalpha(ch)) nw++; ch = c; nc++; if (c == '\n') nl++; } fclose (fIn); /* Write the results */ fOut = fopen (output_file, "w"); if (fOut == NULL) return 2; fprintf (fOut, " %9d %9d %9d %s\n", nl, nw, nc, inputFile); fclose (fOut); return 0; }
__declspec (dllexport) int __cdecl toupperip (char * command, char * output_file) /* convert input to upper case; in process*/ /* Input file is the second token ("toupperip" is the first)*/ { FILE * fIn, *fOut; int c; char inputFile[256];
ExtractToken (1, command, inputFile);
fIn = fopen (inputFile, "r"); if (fIn == NULL) return 1; fOut = fopen (output_file, "w"); if (fOut == NULL) return 2;
while ((c = fgetc (fIn)) != EOF) { if (c == '\0') break; if (isalpha(c)) c = toupper(c); fputc (c, fOut); } fclose (fIn); fclose (fOut); return 0; }
static void ExtractToken (int it, char * command, char * token) { /* Extract token number "it" (first token is number 0)*/ /* from "command". Result goes in "token"*/ /* tokens are white space delimited*/ . . . (see the Examples file return; }
|
By
convention, the first parameter is the command line, while the second
is the name of the output file. Beyond that, always remember that the
function will execute in the same thread as the server thread, so there
are strict requirements for thread safety, including but not limited to
the following:
The
functions should not change the process environment in any way. For
example, if one of the functions changes the working directory, that
change will affect the entire process. Similarly, the functions should not redirect standard input or output. Programming
errors, such as allowing a subscript or pointer to go out of bounds or
the stack to overflow, could corrupt another thread or the server
process itself. More generally, the function should not generate any
unhandled exception because the server will not be able to do anything
other than shut down. Resource leaks, such as failing to deallocate memory or to close handles, will ultimately affect the server application.
Processes
do not have such stringent requirements because a process cannot
normally corrupt other processes, and resources are freed when the
process terminates. A typical development methodology, then, is to
develop and debug a service as a process, and when it is judged to be
reliable, convert it to a DLL.
Program 1 shows a small DLL library with two simple functions, wcip and toupperip,
which have functionality from programs in previous chapters. The code
is in C, avoiding C++ decorated names. These examples do not support
Unicode as currently written.
|