Network Programming with Perl
Lincoln D. Stein
Errata
Found a bug? Send errata reports to lstein@cshl.org.
[errata from the first printing]
[errata from the second printing]
This section contains errata and comments for the second printing of
the first edition (March 2001).
- Page 88 tcp_echo_cli1.pl (Figure 4.1) and
page 116 tcp_echo_serv2.pl (Figure 5.4)
- The echo client and echo server don't play well together because they don't agree on
the end of line character (however, the server will work correctly with telnet, and
the client will work well with other echo servers, including tcp_echo_serv1.pl).
To make the client talk to the server, you must modify it to append CRLF sequences
to the end of each input line, as shown in this revised example.
#!/usr/bin/perl
# file: tcp_echo_cli1.pl
# Figure 4.1: A TCP Echo Client
# usage: tcp_echo_cli1.pl [host] [port]
use strict;
use Socket qw(:DEFAULT :crlf);
use IO::Handle;
my ($bytes_out,$bytes_in) = (0,0);
my $host = shift || 'localhost';
my $port = shift || getservbyname('echo','tcp');
my $protocol = getprotobyname('tcp');
$host = inet_aton($host) or die "$host: unknown host";
socket(SOCK, AF_INET, SOCK_STREAM, $protocol) or die "socket() failed: $!";
my $dest_addr = sockaddr_in($port,$host);
connect(SOCK,$dest_addr) or die "connect() failed: $!";
SOCK->autoflush(1);
while (my $msg_out = <>) {
chomp $msg_out;
$msg_out .= CRLF;
print SOCK $msg_out;
my $msg_in = <SOCK>;
print $msg_in;
$bytes_out += length($msg_out);
$bytes_in += length($msg_in);
}
close SOCK;
print STDERR "bytes_sent = $bytes_out, bytes_received = $bytes_in\n";
Win32 Perl's lack of support for multiplexing across non-socket
filehandles affects the two non-blocking client examples given in
these chapters. See the description of the problem in the errata for Chapter 12 for details.
- Page 364, inline code example at top of page
- The code given truncates the write buffer incorrectly by replacing
the written portion with a single space, rather than with an empty string.
In addition, it will generate a "numeric gt used with non-numeric value"
error when run using strict. The correct code should read:
my $rc = syswrite(SOCK,$data);
if (defined $rc && $rc > 0) { # some data written
substr($data,0,$rc) = ''
} elsif ($! == EWOULDBLOCK) { # would block: not an error
# handle blocking, probably just by trying again later
} else {
die "error on syswrite(): $!";
}
- Page 374, Figure 13.4
- There is a semicolon missing from the end of line 4. It should read:
use IO::Socket;
- Pages 367-370 and Figure 13.2, the IO::Getline module
- You may experience this error when your IO::Getline-using program exits:
(in cleanup) Can't call method "DESTROY" on an undefined value at
/home/lstein/lib/perl/IO/Getline.pm line 32 during global destruction.
The fix is to add this line to the bottom of IO::Getline, just before line 78:
sub DESTROY {}
- Pages 388-389, The IO::SessionSet Module
- There is a bug on lines 103-104. The module croaks when a session times out, but
what it should do is to return no sessions ready for I/O. The fix is as follows:
101 # Call select() to get the list of sessions that are ready for reading/writing.
102 my ($read,$write) =
IO::Select->select($self->{readers},$self->{writers},undef,$timeout)
103 or return; # timeout
- Pages 389-390, The IO::LineBufferedSessionData module (also Appendix A, page 661)
- There is a bug in lines 84 and 89. Replace $self->{buffer} with $self->{inbuffer}
in both places. This bug is also present in the source code distributed prior to
January 21, 2002.
- Figure 14.7: Daemon module
- When using Perl versions earlier than 5.6, replace line 5, which brings in the Carp::Heavy
module, with this line:
5 use Carp;
- In the regular expression in lines 93 and 94, replace the character class "A-z" with "A-Z".
The lines should read:
93 chdir $1 if $CWD =~ m!([./a-zA-Z0-9_-]+)!;
94 croak "bad program name" unless $0 =~ m!([./a-zA-Z0-9_-]+)!;
This section contains errata and comments for the first printing of the
first edition (December 2000).
- Page xx, under Internet RFCs
- The acronym for The Internet Engineering Task Force is
IETF, not IEFT.
- Page 14, third paragraph
- This paragraph refers to Appendix C for a brief summary of
Perl's special variables. In fact, Appendix B contains this
information.
- Page 26, third paragraph
- This paragraph refers to the IO:Handle module. This should read
IO::Handle instead.
- Page 45, third line from bottom
- This sentence should read ...and killing excess children when
the load is low, rather than the low is low.
- Page 75, Figure 3.4
- Line 8 of daytime_cli.pl should read:
my $packed_addr = inet_aton($address);
In addition, neither of the IP addresses given for daytime servers in the example
at the top of the page work (because these services have been discontinued). Instead,
use 24.188.53.249:
% daytime_cli.pl 24.188.53.249
Sat Jan 6 19:11:22 2001
- Page 78, command-line example
- The host named presto.cshl.org should be replaced by pesto.cshl.org.
- Page 79
- If you are looking for a daytime server to test the script with,
try the hostname daytime.modperl.com.
- Page 89
- If you need an echo server to test tcp_echo_cli1.pl you
may use echo.modperl.com:
% tcp_echo_cli1.pl echo.modperl.com
hi
hi
there
there
Alternatively, run the reverse echo server in tcp_echo_serv1.pl
- Pages 147: Net::Telnet
- Under Perl 5.6, Net:Telnet version 3.02 fails one of its
three tests during installation. However, this does not
adversely affect any of the code examples that use it.
- Page 159
- In Figure 6.6, the change_passwd_ssh.pl script, insert the
following line after line 7:
use constant DEBUG => 0;
- Page 280
- The first normal paragraph on this page refers to
HTML::Tree objects. This should read
HTML::TreeBuilder.
- Page 281, description of HTML::TreeBuilder->parse
- The paragraph should end with the following sentence:
If parse() is successful, it will return a copy of the HTML::TreeBuilder
object. If something goes wrong, it will return undef.
- Page 281, second to last paragraph
- The text gives a common idiom for creating and parsing HTML
files in one statement. However, this statement will leak a
small amount of memory if the call to parse_file() fails, and therefore should
be avoided in a loop that will be executed many times. It is
safest to create the HTML::TreeBuilder object, use it
and formally deallocate it, as shown here:
$tree = HTML::TreeBuilder->new;
if ($tree->parse_file('rfc2010.html')) {
# use the parse tree
}
$tree->delete;
- Page 283, Figure 9.18 the get_url3.pl script
- This script does not check for the case in which the response
does not provide a content type. Strictly speaking it should do
so, as the HTTP specification allows (but strongly discourages) Web
servers to omit this field. Run the script with the -w switch
to detect and report this case.
I have recently learned that the Win32 port of Perl does not support
select() on non-socket filehandles. This means that the select()
function and the IO::Select class cannot be used to multiplex normal
filehandles such as STDIN or STDOUT. IO::Poll will also fail on
Windows systems when used with non-socket filehandles.
Although they may seem to work, all the examples that multiplex across
non-socket filehandles will fail on Win32 systems. Instead of pausing
until STDIN or STDOUT are ready, the main I/O loop will race, causing
a noticeable increase in CPU load.
The following examples in Chapters 12, 13 and 16 are affected by this
problem:
- Figure 12.1: A multiplexed client
- Figure 13.1: Reading from STDIN with IO::Getline
- Figure 13.7: The gab6.pl script
- Figure 16.1: The gab7.pl script
Because Win32 systems support select(), IO::Select, and IO::Poll on
sockets, all multiplexed server examples in these chapters work as
expected.
Other errata
- Page 346
- The text describing lines 18-24 says "...we use sysread() to read up to 2K bytes of data..."
This should read "up to 1K bytes of data."
Win32 Perl's lack of support for multiplexing across non-socket
filehandles affects the two non-blocking client examples given in
these chapters. See the description of the problem in the errata for Chapter 12 for details.
- Page 374, Figure 13.4
- There is a semicolon missing from the end of line 4. It should read:
use IO::Socket;
- Pages 367-370 and Figure 13.2, the IO::Getline module
- You may experience this error when your IO::Getline-using program exits:
(in cleanup) Can't call method "DESTROY" on an undefined value at
/home/lstein/lib/perl/IO/Getline.pm line 32 during global destruction.
The fix is to add this line to the bottom of IO::Getline, just before line 78:
sub DESTROY {}
- Page 372
- Following line 16 of the code example, the descriptive text reads "...which returns
up to 4K bytes of data...". This should read "up to 2K bytes of data."
- Figure 14.7: Daemon module
- When using Perl versions earlier than 5.6, replace line 5, which brings in the Carp::Heavy
module, with this line:
5 use Carp;
- In the regular expression in lines 93 and 94, replace the character class "A-z" with "A-Z".
The lines should read:
93 chdir $1 if $CWD =~ m!([./a-zA-Z0-9_-]+)!;
94 croak "bad program name" unless $0 =~ m!([./a-zA-Z0-9_-]+)!;
IO::Poll version 0.04 can be found in Perl version 5.7 and higher. Do
not try to use the version in Perl 5.6. A copy of IO::Poll 0.04 can
be found in the source code distribution at this site.
Win32 Perl's lack of support for multiplexing across non-socket
filehandles affects the multiplexed client example given in this
chapters. See the description of the problem in the errata for Chapter 12 for details.
- Page 495, Figure 16.1
- Line 6 should read as follows:
use IO::Poll 0.04 qw(POLLIN POLLOUT POLLERR POLLHUP);
- Page 505, Figure 17.3
- Because of recent changes in the Perl interpreter, the
urg_recv.pl may give a syntax error when used with Perl
5.6 or higher. Replace lines 9 and 10 with the following:
print $r ? ("got ",length($data)," bytes of urgent data: $data\n")
: ("recv() error: $!\n");
- Page 507
- The same caveat applies to urg_recv2.pl, and is fixed in the
same way.
- Pages 509-526
- Because of the difficulty in using h2ph to generate the .ph files
required by the Sockatmark.pm module, I have recently written a C-language
extension module named IO::Sockatmark. It is available on CPAN,
and in the code archive on this site. If you have encounter problems getting
the pure-Perl version of Sockatmark.pm to work, I suggest you replace it with
IO::Sockatmark. You will need a C compiler to do this.
The modifications required to use IO::Sockatmark in the
"travesty" code examples are very minor. In figures 17.6 and
17.7, simply change:
use Sockatmark;
to
use IO::Sockatmark;
- Pages 527-528
- All references to udp_daytime.pl in the text and Figure
18.1 should be replaced with udp_daytime_cli.pl.
- Pages 556-562, Figure 19.2
- The chat_client.pl script works as printed. However, the
user interface is a unfriendly. In the version provided in the
script archive, I have added a minimal /help command that
provides help information for the novice user.
I have also changed timed_chat_client.pl and the chat clients from
chapters 20 and 21 in the same way.
- Pages 566-567, Figure 19.5
- There is an error in the chat_server.pl script on line
37. The %dispatch hash should be replaced by %DISPATCH:
unless my $dispatch = $DISPATCH{$code};
- Page 598, Figure 20.3
- As written, the IO::Interface module will work, but only provided that the
.ph include files are made correctly. Recent versions of
h2ph fail to create a correct net/if.ph files on some
systems. Either hand-edit the .ph file to contain the correct
definitions for IFF_BROADCAST, IFF_LOOPBACK and so on, or use
the CPAN version of IO::Interface.
- Pages 651-654, The Net::NetmaskLite module
- Lines 15, 20, 25 and 30 refer to the tonum() function. In fact,
it is the _tonum() function.
Network Programming in Perl: Home Page
Lincoln D. Stein, lstein@cshl.org
Cold Spring Harbor Laboratory
Last modified: Fri Apr 12 11:37:25 EDT 2002