I know I should have started this earlier than version 3.0. I'm working on a time machine right now to help rectify the situation.
| Release | Description of changes |
| 3.0.8, 2009-02-16 | getpeername() man page example [book v3.0.7 pp. 95-96]: replaced
"&" with real ampersands (C doesn't like &—who
knew) in call to getpeername(). Added address-of operators (&)
before the "s->sin_addr" and "s->sin6_addr" parameters to both
calls to inet_ntop(). Thanks to Rafael for reporting these.
getpeername(s, (struct sockaddr*) |
| 3.0.9, 2009-02-18 | getpeername() man page example again (I know!) [book v3.0.7 p. 96]:
replaced AF_INET with AF_INET6 where appropriate. How many bugs can I
have in 10 lines of code? I wrote a short program that counted exactly
how many bugs I had, and it was this: -37! Thanks again to Rafael who
won't let me off the hook until I get it right. :)
} else { // AF_INET6
[... snip ...]
inet_ntop( |
| 3.0.10, 2009-02-23 | bind() man page example [book v3.0.7 p. 81]: need an address-of on
myaddr. (Thanks to Venkat for the report!)
bind(s, (struct sockaddr*)myaddr, sizeof myaddr); bind(s, (struct sockaddr*)&myaddr, sizeof myaddr);I also changed and added some comments in the same example [book v3.0.7 pp. 80-81]. The "proper" way doesn't demonstrate error checking, so it's not very proper. // |
| 3.0.11, 2009-02-24 | Section 5.2 socket() syscall example [book v3.0.7 p. 25]: forgot to
declare the type of hints. Also added a clarifying comment about the
proper use of the getaddrinfo() results linked list. (This bug caught by
Kaio—thanks, as always!)
struct addrinfo *res; struct addrinfo hints, *res;and
// do the lookup
// [pretend we already filled out the "hints" struct]
getaddrinfo("www.example.com", "http", &hints, &res);
// [again, you should do error-checking on getaddrinfo(), and walk
// the "res" linked list looking for valid entries instead of just
// assuming the first one is good (like many of these examples do.)
// See the section on client/server for real examples.]
|
| 3.0.12, 2009-02-24 | And the hits just keep coming today! These are from Mick—a
couple of typos.
Section 3.1, "IP Addresses, versions 4 and 6" [book v3.0.7 p. 9]: and was common written in "dots and numbers" form and was commonly written in "dots and numbers" formAnd, same section [book v3.0.7 p. 10]: That we need not just twice as many address, not a billion times as many That we need not just twice as many addresses, not a billion times as many |
| 3.0.13, 2009-03-23 | A big batch today from Rainer Kupke: "&" removals and a
quick note about using errno in multithreaded environments.
couple of typos. Hopefully this is all the stupid & errors caused
by my lame indiscriminate use of CDATA in my source XML...
Section 9.2, "bind()" [book v3.0.7 p. 81]: bind(s, (struct sockaddr*)myaddr, sizeof myaddr); bind(s, (struct sockaddr*)&myaddr, sizeof myaddr);or bind(s, (struct sockaddr*)&Section 9.18, "recv(), recvfrom()" [book v3.0.7 p. 116]: byte_count = recvfrom(sockfd, buf, sizeof buf, 0, &Section 9.19, "select()" [book v3.0.7 p. 118], lots of them bundled here... Gah, sorry! FD_ZERO(&Section 9.21, "send(), sendto()" [book v3.0.7 p. 122]: send(stream_socket, &Section 5.2, "socket()—Get the file descriptor!" [book v3.0.7 p 25]: The global variable errno is set to the error's value (see theSection 9.10, "errno" [book v3.0.7 p 97], add the following paragraph to the end of the description: One thing to note, for you multithreading enthusiasts, is that on most systems errno is defined in a threadsafe manner. (That is, it's not actually a global variable, but it behaves just like a global variable would in a single-threaded environment.) |
| 3.0.14, 2009-09-08 | A few changes, one substantial:
Section 6.3, "Datagram Sockets" [book v3.0.7 p 41]: type change in listener.c line 38:
Section 6.3, "select(): Synchronous I/O Multiplexing" [book v3.0.7 p XX]: added text: This being said, in modern times Section 7.4, "Serialization—How to Pack Data" [book v3.0.7 pp. 55-57]: addition and changes to ieee754.c: #include <inttypes.h>
long double unpack754(
printf("float encoded: 0x%08
printf("double encoded: 0x%016
Section 7.4, "Serialization—How to Pack Data" [book v3.0.7 pp. 58-62]: multitude of changes, too many to list, to pack2.c to get it to function properly on 32-bit and 64-bit machines. It now relies on C99 features, but it was the cleanest way to get it portable. Modern gcc should have no trouble. (Thanks to Bruce L. for the catch and testing.) Section 7.4, "Serialization—How to Pack Data" [book v3.0.7 pp. XX-XX]: text added: [THE END] (Before I begin this section in earnest, I should tell you that there are libraries out there for doing this, and rolling your own and remaining portable and error-free is quite a challenge. So hunt around and do your homework before deciding to implement this stuff yourself. I include the information here for those curious about how things like this work.) Actually all the methods, above, have their drawbacks and advantages, Section 7.4, "Serialization—How to Pack Data" [book v3.0.7 pp. XX-XX]: text added: But if you want your source code to be portable, that's an assumption you can't necessarily make. (On the other hand, if you want things to be fast, you should optimize this out on platforms that don't need to do it! That's what htons() and its ilk do.) |