#!/usr/local/bin/perl -Tw ###################################################################### # client.pl # Tom Kelliher, CS 318 # # This program is a demonstration of a simple client application. The # client merely reads a brief message from the server. It works with # its companion program, server.pl, as well as other simple servers, # such as daytime. # # By default, the client attempts to contact localhost at port 50001. # An alternate server and port can be specified: # # client.pl [server_hostname [server_port_number]] # # Note that taint checking (-T) has been enabled in addition to the # standard warnings (-w) on the shebang line. ###################################################################### # Initial declarations. require 5.002; use strict; use sigtrap; # Use some basic signal traps. use Socket; # Use the socket library. # Globals. my $SERVER_HOSTNAME = "localhost"; # Default server hostname. my $SERVER_PORT = 50001; # Default server port. my $BUFFER_LEN = 1400; # Maximum amount of data we # want to receive in a single # packet. ###################################################################### # MAIN ###################################################################### MAIN: { my $server = shift || $SERVER_HOSTNAME; # Server hostname. my $sport = shift || $SERVER_PORT; # Server port number. my $sipaddr; # Server IP address. my $paddr; # Packed address # (port number and IP # address). my $proto; # TCP protocol number. my $sockaddr; # Packed address of # local end of socket. my $lport; # Local port number my $lipaddr; # Local IP address. my $line; # Line of input. # If we've taken a host name from the command line, it's now # tainted. If it is only letters, digits, and "dots", we'll go # ahead and untaint it. if ($server =~ /^([\w\d.]+)$/) { $server = $1; } else { die "Bad data in server: $server.\n"; } # If we've taken a port number from the command line, it's now # tainted. If it is only letters and digits, we'll go ahead and # untaint it. if ($sport =~ /^([\w\d]+)$/) { $sport = $1; } else { die "Bad data in server port: $sport.\n"; } # If the port number has letters, assume it was given symbolically # and attempt to retrieve the corresponding port number. if ($sport =~ /\D/) { $sport = getservbyname($sport, "tcp"); } die "No port.\n" unless $sport; # Get the IP address of the server. $sipaddr = inet_aton($server) or die "No host: $server.\n"; print "Server: $server\nServer Port: $sport.\n"; # Get the TCP protocol number. $proto = getprotobyname("tcp"); # Attempt to create a socket. SOCK is the handle. This socket # uses a protocol family of Internet, it's a stream socket, and it's # a TCP socket. socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die "Socket: $!"; # Create the packed server address and attempt to connect to the # server, using the just-created socket. $paddr = sockaddr_in($sport, $sipaddr); connect(SOCK, $paddr) or die "Connect: $!"; # Get the packed address of this end of the socket and unpack it. $sockaddr = getsockname(SOCK); ($lport, $lipaddr) = sockaddr_in($sockaddr); print "Using Local Port: $lport.\n"; print "Server says:\n"; # Start receiving data from the server. The fourth parameter to # recv() is option bits, usually 0. recv(SOCK, $line, $BUFFER_LEN, 0); # The message may have been fragmented into several packets. # We continue receiving packets until receive returns a packet # with no data, signifying the end of the message. while (length($line) > 0) { print $line; recv(SOCK, $line, $BUFFER_LEN, 0); } close(SOCK); exit 0; }