UNIX Network Programming, Volume 1, Second Edition
Author: W. Richard Stevens
Publisher: Prentice Hall
Price: $59 US
Reviewer: David Bausum
In 1990 I chanced upon a review of a book which sounded interesting. I tucked the author's name and the book's title away in my memory, and several months later when I was in a large bookstore, I purchased Master and Commander by Patrick O'Brian. Within a dozen pages I was hooked. In the intervening years I've enjoyed all of the 18-volume series dealing with the adventures of Maturin and Aubrey during the Napoleonic Wars. The point of this story is that, when I find an author I like, I'll read as many of his books as I can. I've found the same approach works with technical books.
In LJ issue 42, I described how I discovered W. Richard Stevens' Advanced Programming in the UNIX Environment. In conjunction with the project described in that review, I needed to learn something about UNIX network programming. By coincidence, Stevens' first book was entitled UNIX Network Programming. Without hesitation I ordered the book in late 1996, even though it was six years old and possibly dated. For reasons I don't quite understand (but put down to my own deficiencies), UNP and I never quite clicked in the way APUE and I did. Even so, when I learned in the fall of 1997 that a second edition of UNP was about to be released, I ordered a copy as soon as it was available.
Generally, I am leery of new editions. All too often the book has a new preface, a new cover (with the words “new” or “improved” in big letters), a new copyright date, some cosmetic reshuffling of material, and little else. Some publishers and authors specialize in this game. That is not true for this book. The complete title gives a hint that the new edition is real. (In fact, three volumes are planned for the second edition.) A cursory glance at the table of contents confirms that this is an entirely new book. Within several days of working with it, something clicked, and the basics of UNIX network programming fell into place for me.
I like working with Stevens' books because he makes beautiful books. The operable words here are “makes beautiful”. The second word is important because a beautiful book—one that is well organized and whose pages contain a balanced presentation of text (explaining the topic at hand), diagrams (showing relationships), tables (summarizing or detailing particular items) and code—makes the beginner's journey through new material much easier. The first word is important because a beautiful book does not just happen. It is made in the same way a medieval work of art was made: by an individual who spent years mastering a field, and then used that mastery in various projects. One of the tools Stevens uses is troff. If you have an interest in design and layout, you might profit from the part of Stevens' web site dealing with typesetting and troff resources. Lest the reader think I'm making too much of this, let me note that I'm currently working my way through several books in another area (best left unnamed). Unfortunately, none are as well organized (beautiful in the sense described above) as Stevens' books are. As a result, I find each to be difficult to work with.
The new book has a complete rewrite of UNP's chapters on Berkeley sockets and System V's TLI. Although it is over 1000 pages long, it is not padded and does not (unnecessarily) duplicate material from Stevens' earlier books. There is very little general (non-network) programming covered in the book. References to APUE are made as necessary. Similarly, Stevens refers to the TCP/IP series rather than duplicates material covered there. Also, he has managed to cut through the generalities about networking that occupied 10% of the first edition of UNP. For example, on page 6 of the new book, Stevens presents code for a working client program, and on page 13 he presents code for the complementary server. When a client connects, the server gets the time and sends it to the client which prints it and quits. The result is trivial (just as the classic “hello world” program is), but it provides a working client-server program hardly a dozen pages into the book.
This new book mixes working, portable, real-world, annotated code with text, diagrams and tables to document the sockets (and XTI) API. Over 50 programs and 100 functions are discussed in the book.
Working code means you can obtain all the examples used in the book from Stevens' home page (http://www.kohala.com/~rstevens/). For example, in less than an hour I downloaded a 226KB gzipped tar file, expanded it, ran Stevens' configuration routine, ran the Makefile which builds the library used by all programs and subsequent Makefiles, and compiled the programs for Chapter 1. During the make of the library, I had a small problem because I don't have a threads library on my system. A quick change to the library Makefile (removing references to threads) fixed things. I've not compiled all the programs supplied, but the ones I have compile and run the way the book says they should.
Portable means the code will compile not only on Linux systems (yes, Linux is one of the systems used as an example in the book), but on BSD, HP UNIX, Digital UNIX, Solaris (Sun/SPARC) and Unixware systems. Some of these are running IPv4 protocol stacks, others are running IPv6. The code “doesn't care”; it is portable. One of the themes running through the book is how a programmer can write library routines which are protocol stack and system independent. Portable also means POSIX compliant, in particular Draft 6.6 (March 1997) of P1003.1g.
Real world means the code deals with errors. A programmer must constantly ask “how can this code, this library call, this function fail? If it does, how can I either gracefully end the program or recover and keep going?” For many new programmers this is a difficult lesson to learn. Stevens worries about this, and the beginner will benefit from his examples.
Annotated means that when code is discussed in the book, the printed listing includes the subdirectory and file name for the code, the lines in the listing are numbered, and the discussion in the text puts an appropriate, line-number range in the margin of the text. This makes it easy for you to move from text (discussing a range of lines) to the printed listing (in the book) to the actual file (on your hard disk).
The book contains much more than code. Stevens writes well. He has developed a style which allows him to interrupt his narrative discussion with historical and current observations. He does this by adjusting the margins and changing the font. It is easy to skip the “notes” on a first reading and then focus on them on subsequent passes through a section or chapter. One example of the timeliness of these notes is his explanation of denial of service attacks on page 99. When appropriate, Stevens includes a diagram which provides an alternate explanation for a topic. Also, when appropriate, he includes a table which summarizes similar pieces of a topic. The result is a work which is encyclopedic without being stifling.
I find I can approach a new chapter or section and first study the code, then examine the diagrams, then read the text and finally repeat the process, possibly in a different order. As I understand more, the various approaches reinforce each other so that the whole ends up being greater than the sum of its parts. Finally, the various tables are natural places to refer back to, once I understand a topic or when I have a specific question.
The book is organized into four parts. The first is 50 pages (two chapters) of introductory material. This includes the working client-server program referred to above. The second is 200 pages (seven chapters). This discusses the basic networking functions utilized by Berkeley sockets (socket, bind, etc.). This part contains many programs and program fragments. The third is 500 pages (18 chapters) and deals with miscellaneous topics. The fourth is 120 pages (seven chapters) and covers the basic API for X/Open Transport Interface. The beginner will want to read the first two parts carefully. The more advanced reader should skim part one to get a sense of Stevens' style and then refer to part two as needed. To a large degree, the chapters in part three are independent of each other. That means, once the basics from part two are clear, it is very easy to pick and choose among the topics discussed in part three. If you are interested in threads, skip to Chapter 23. If you are interested in IPv4 and IPv6, turn to Chapters 10 and 24.
Rather than give more details here, I will invoke the spirit of Linux and refer you to Stevens' web site. If you look there, you will find information about each of Stevens' existing books, and you will find the Table of Contents, the Preface and a sample chapter of UNIX Networking Programming, Volume 1, Second Edition. In addition, you will find the code for the book and a README file describing the installation of the software, as well as the typesetting and troff references. Finally, you will find information about Volume 2 (Interprocess Communication) and Volume 3 (Applications). Both these volumes were still under construction at the time I wrote this review (February). Together the three volumes comprise the second edition of UNIX Network Programming.
David Bausum received a Ph.D. in mathematics from Yale in 1974. Since the early 80s, most of his energy has gone into software development and related activities. He coedited The Journal of Military History Cumulative Index: Volumes 1-58, 1937-1994. He can be reached via e-mail at firstname.lastname@example.org.