Title: The Client/Server Toolkit for C and C++ Programmers
Authors: Steven Lemmo and
Rich Grehan
Publisher: NobleNet, 1996
Pages: 423, bundled with CD
Price: $49.95The Client/Server Toolkit is not the typical programming book, in which the text is the star attraction and the bundled code, while important, remains secondary. As a book/CD hybrid, the Toolkit is a little hard to categorize. The book is part tutorial, introducing Client/Server programming, and Remote Procedure Call (RPC) techniques in particular. It is also a sort of user guide for WinRPC, the software on the CD.
WinRPC is a system that enables you to split an existing application into client and server halves, ideally without modifying the application's original source code. You can then run the resulting client/server application using WinRPC's network simulator. Finally, as "noble" as the authors' intentions may be, it's hard to overlook the Toolkit's marketing connection to NobleNet it is also a demo for NobleNet's line of commercial RPC products. The book makes clear that to create a sizeable application (one having more than 20 distributed functions) to run on a real network (where client and server reside on separate machines) you must purchase the WinRPC "Professional" Edition. Apparently the universe still isn't handing out free lunches.
An important question then is how much the Toolkit stands on its own as an educational/modeling tool, as opposed to being just an elaborate (if well made) demo. I'm glad to say it pretty much succeeds as the former. For those who want to get a taste of RPC programming, the Toolkit makes an excellent introduction. It could also come in handy for modeling the various ways of splitting a monolithic application into client and server parts. I would point out, however, that neither the book nor the CD would be very useful if considered separately. They must be used together.
The book's strength is in the detail and clarity with which it leads us through the intricacies of RPC programming. It's full of well drawn figures and instructive code snippets. But for all that, this book is not something you'd want to read on a plane, or curl up with it in bed. You need a computer by your side to bring it to life.
You can skip the first chapter if you already have a pretty good idea what a client/server application is. After explaining the overall what and why of client/server programming, this chapter describes a few typical applications that work well under the client/server model. From there we jump to a chapter on partitioning, the process by which code is relegated to either the client or server side of the tracks. The authors state that "...partitioning can be as easy as slicing a pizza pie with a knife or as hard as equally and precisely dividing the same hot pizza with your bare hands." I'd say that was an apt description, after messing with WinRPC a little bit myself. This chapter provides some partitioning dos and don'ts to help you avoid making too big a mess. Experimentation, with the help of WinRPC, is heartily encouraged by the authors.
It's the chapter on IDL where things start to get interesting. IDL, or Interface Definition Language, is the little language that enables everything to happen behind the scenes. If distributed-object computing becomes the Next Big Thing as some pundits predict, we'll all be up to our necks in IDLs, so perhaps we had better get used to them. WinRPC IDL code looks a lot like C, with some extra uglies thrown in. You write IDL code to tell WinRPC the things it can't deduce from your source files, such as the direction of data flow through a function argument. WinRPC compiles your IDL to produce all the code needed to hook the client's function calls to server functions. A big plus is that the code generated is good ol' C, so it makes a great tool for studying RPC.
Well, almost great. As is typical of generated code, WinRPC's isn't pretty. Here's a sample only a mother could love:
if(!xdr_ez_p2array(xdrs, (cadd_t**)&objp->p2array, (u_int*)&objp->size, (u_int)objp->size, sizeof(Integer), (xdrproc_t)xdr_Integer_p, (u_int)opt)) { return (FALSE); }Fortunately, the authors are quite adept at walking us through functions such as this.
The other meaty chapters include one on XDR, a platform-independent data format developed by Sun; a chapter on memory management and RPC; and a chapter on customization, somewhat euphamistically entitled "Programmer Participation."
The first few chapters of the book give the impression that converting an application to client/server can be painless. Maybe it can, if you don't try anything fancy. When you get to the chapter on memory management, the harsh realities of RPC begin to sink in. Problems crop up when you pass arguments involving multiple indirection, such as: pointers to pointers, pointers to structures containing pointers, pointers to arrays containing pointers, etc. In these cases, WinRPC needs some assistance from a human programmer, or it will likely generate code that leaks memory.
This is not because of a deficiency in WinRPC; it's because WinRPC lacks certain information about where the memory came from or who was supposed to clean it up. You may or may not be able to fix this situation with a few extra lines of IDL. IDL has no executable statements, and in some cases you must bite the bullet. You must supply routines to explicitly copy data from one place to another.
Playing with WinRPC
The book devotes a separate chapter to each of four sample applications (not counting a ho-hum "Hello, World" app) that come on the CD. The CD contains the complete source and RPC files for each application, but you can fire up the IDL precompiler and recreate the stubs if you want.
I thought the authors came up with a good mix of sample applications not too complex, but still interesting. There's an application that implements a server-side compute engine, an imaging application in which the client talks to two servers (a screen grabber and a simple image processor), a remote data-feed application (simulates a remote data source by repeatedly querying the system memory manager about free memory left), and a database application using an ODBC driver. Each of these applications ran without a hitch on my system. Conceivably, you could modify these sample applications (source code is included), and without too much work, have something useful for small projects.
WinRPC supplies an IDE with enough smarts to create and run makefiles with C/C++ compilers. Compilers supported are Borland C/C++ 3.x or better, and Microsoft C 7.x or 8.x, or Microsoft Visual C++ 1.0, 1.5, or 2.0 (16-bit). The code generated is intended to run on Windows 3.1 and up, so you may have to coerce newer compilers to generate 16-bit code (if possible). The IDE provides menus to open projects, open files, edit them on a simple built-in editor, and run the IDL precompiler separately or as part of a Build. You can specify which parts of the project you want to rebuild (client or server or both). There's an option to produce trace statements in the generated C source files for debugging purposes. That's about all there is to the IDE it's functional, but nothing fancy.
C++ and RPC
C++ makes its official appearance in this book in Appendix B. The Toolkit code might compile okay in C++, but there are no class definitions or other C++-isms in the Toolkit source code; it's straight C.
Appendix B sort of shows how to implement a distributed C++ object. I say "sort of" because the authors aren't nearly as thorough here as they are in the rest of the book. They pretty much tell you which files you have to create, and which pieces go where, and then leave you on your own this time there's no sample source code on the CD to help you along.
After hacking away at both my own source code and the auto-generated stuff for a few hours, I finally got the example in the Appendix to work. The example involves creating a simple class with Set and Get member functions. The instantiated object lives on the server and you call its member functions through a proxy on the client side. Even with this simple example, I felt like I was splitting the proverbial pizza with a chain saw. What I concluded from this example is that you can distribute simple C++ objects with WinRPC, but you may not want to.
This appendix does have some neat diagrams, and Patterns buffs will appreciate that the entire appendix is presented as one big pattern. I am not exactly sure why. I suppose it seems like a cool thing to do, but in this case it doesn't make the material any easier to understand.
Conclusion
It's not the pattern-speak that impresses me about the Toolkit. I am impressed with the authors' ability to keep up a friendly and accessible tone, even while grinding through the nitty gritties of RPC. The only price we readers must pay for this friendliness is having to plod through occasional excesses of chattiness and hype. (The book does sort of sell WinRPC every chance it gets.) The software on the CD is easy to install and use, with the caveat that it's basically a Lite version of WinRPC. To produce industrial strength RPCs, you'll probably need something more robust. No doubt NobleNet would like to sell you their professional version, but that's a whole 'nother article that I'm not going to write. You can investigate for yourself at their website: http://www.noblenet.com. o
Marc Briand is managing editor of C/C++ Users Journal. He loves programming, writing, and too many other things for his own good. However, he hates to work, which is why he is an editor. He may be reached at mbriand@mfi.com.