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]

Second Printing (March 2001)

This section contains errata and comments for the second printing of the first edition (March 2001).

Chapter 4

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";
      

Chapter 13: Nonblocking I/O

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.

Chapter 14: Bulletproofing Servers

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_-]+)!;
    

First Printing (December 2000)

This section contains errata and comments for the first printing of the first edition (December 2000).


Preface

Page xx, under Internet RFCs
The acronym for The Internet Engineering Task Force is IETF, not IEFT.

Chapter 1

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.

Chapter 2

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.

Chapter 3

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.

Chapter 4

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


Chapter 6

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;
      

Chapter 9

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.


Chapter 12: Multiplexed Applications

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:

  1. Figure 12.1: A multiplexed client
  2. Figure 13.1: Reading from STDIN with IO::Getline
  3. Figure 13.7: The gab6.pl script
  4. 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."

Chapter 13: Nonblocking I/O

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."

Chapter 14: Bulletproofing Servers

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_-]+)!;
    

Chapter 16: IO::Poll

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);
      

Chapter 17: TCP Urgent Data

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;
      


Chapter 18: The UDP Protocol

Pages 527-528
All references to udp_daytime.pl in the text and Figure 18.1 should be replaced with udp_daytime_cli.pl.


Chapter 19: UDP Servers

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};
      


Chapter 20: Broadcasting

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.

Appendix A: Additional Source code

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