710 likes | 961 Views
CMPE 587 Advanced Network Programming. PERL PROGRAMMING by Buğra Başaran Caner Kurtul. What is Perl?. Perl is an acronym for "Practical Extraction and Report Language ” Initially designed as a glue language for Unix, now Perl is available for most other operating systems.
E N D
CMPE 587Advanced Network Programming PERL PROGRAMMING by Buğra Başaran Caner Kurtul
What is Perl? • Perl is an acronym for "Practical Extraction and Report Language” • Initially designed as a glue language for Unix, now Perl is available for most other operating systems. • Because it runs nearly everywhere, Perl is one of the most portable programming environments available today. • Perl is a free software. • Perl has taken good ideas from nearly everywhere and installed them into an easy-to-use mental framework.
Compiler Program Intermediate Format Syntax & sematic errors output Interpreter Compilation vs. Interpretation In Perl • Perl is an interpreted language, you can just execute it like a batch file or shell scripts.
Basic Syntax • Perl is free form - whitespace doesn't matter. • All perl statements end in a ; (semicolon), like C. • Case sensitive • Comments • begin with # (pound sign) • everything after the #, and up to the end of the line is ignored. • the # needn't be at the beginning of the line. • There is no way to comment out blocks of code
A Basic Perl Program #!/usr/local/bin/perl # Program to do the obvious print 'Hello world.'; How to run: perl hello.pl(file is given as parameter to perl interpreter) hello.pl(first, file should be changed toexecutable mode) perl -w hello.pl(shows the warnings) perl -d hello.pl(run the program with a debugger) Without a file : perl -e ‘ print "Hello world." ‘ How to take help: perldoc –f undef (to take help about undef function) perldoc -f localtime (to take help about localtime function) hello.pl
Scalar Variables No need to define types explicitly. A variable can be assigned different types of values during the execution of the program. $answer = 42; # an integer $pi = 3.14159265; # a real number $avocados = 6.02e23; # scientific notation $pet = ”Camel”; # a string $sign = ”I love my $pet”; # string with interpolation $cost = ‘It costs $100’; # string without interpolation $thence = $sign; # another variable’s value $num = $answer * $pi; # result of an expression $exit = system(”vi $file1”); # numeric status of a command $cwd = `pwd`; # string output from a command
Operations & Assignments on Scalar Variables • Perl uses all the usual C arithmetic operators: $a = 1 + 2; # Add 1 and 2 and store in $a $a = 3 - 4; # Subtract 4 from 3 and store in $a $a = 5 * 6; # Multiply 5 and 6 $a = 7 / 8; # Divide 7 by 8 to give 0.875 $a = 9 ** 10; # Nine to the power of 10 $a = 5 % 2; # Remainder of 5 divided by 2 ++$a; # Increment $a and then return it $a++; # Return $a and then increment it --$a; # Decrement $a and then return it $a--; # Return $a and then decrement it $a = $b = $c = 0;
Operations & Assignments on Scalar Variables (continued) • For strings Perl has the following among others: $a = $b . $c; # Concatenate $b and $c $a = $b x $c; # $b repeated $c times • To assign values Perl includes: $a = $b; # Assign $b to $a $a += $b; # Add $b to $a $a -= $b; # Subtract $b from $a $a .= $b; # Append $b onto $a • when Perl assigns a value with $a = $b it makes a copy of $b and then assigns that to $a. Therefore the next time you change $b it will not alter $a.
Interpolation Details • The following code prints apples and pears using concatenation: $a = ’apples’; $b = ’pears’; print $a.’ and ’.$b; print '$a and $b'; # prints $a and $b print "$a and $b";# printsapples and pears
Example Name Result $a && $b And $a if $a is false, $b otherwise $a || $b Or $a if $a is true, $b otherwise !$a Not True if $a is not true $a and $b And $a if $a is false, $b otherwise $a or $b Or $a if $a is true, $b otherwise not $a Not True if $a is not true $a xor $b Xor True if $a or $b is true, but not both Logical Operators
Some File Test Operators Example Name Result -e $a Exists True if file named in $a exists -r $a Readable True if file named in $a readable -w $a Writable True if file named in $a writable -d $a Directory True if file named in $a is a directory -f $a File True if file named in $a is a regular file -T $a Text File True if file named in $a is a text file
Some Numeric and String Comparison Operators Comparison Numeric String Return Value Equal == eq True if $a is equal to $b Not Equal != ne True if $a is not equal to $b Less Than < lt True if $a is less then $b Greater Than > gt True if $a is greater then $b Less than or Equal <= le True if $a is not greater then $b Greater than or equal >= ge True if $a is not less then $b Comparison <=> cmp 0 if equal, 1 if $a greater, -1 if $b greater
Array Variables • Array variable is a list of scalars (i.e. numbers and strings). Array variables have the same format as scalar variables except that they are prefixed by an @ symbol • No need to define size for an array. It grows automatically when new elements are added. @food = ("apples", "pears", "eels"); @music = ("whistle", "flute"); @chars = ’a’..’z’; @ints = 1..20; @chars2=@chars; #chars2 gets all elements of chars • The array is accessed by using indices starting from 0, and square brackets are used to specify the index $food[2] #returns eels $food[-1] #returns eels $food[10] = “banana” # food[3]..food[9] can be uninitialized. @moremusic = ("organ", @music, "harp"); @moremusic = ("organ", "whistle", "flute", "harp"); • A neater way of adding elements is to use the statement push(@food, "eggs"); #pushes eggs to end of the array @food
Array Variables (continued I) • To push two or more items onto the array: push(@food, "eggs", "lard"); push(@food, ("eggs", "lard")); push(@food, @morefood); • The push function returns the length of the new list. • To remove the last item from a list and return it use the pop function. $grub = pop(@food); # Now $grub has last element of @food • To remove the first item from a list and return it use the shift function. $grub = shift @food; • It is also possible to assign an array to a scalar variable $f = @food; #assigns the length of @food $f = "@food"; #turns the list into a string with a space #between each element • This space can be replaced by any other string by changing the value of the special $" variable. This variable is just one of Perl's many special variables.
Array Variables (continued II) • Arrays can also be used to make multiple assignments to scalar variables: ($a, $b) = ($c, $d); #Same as $a=$c; $b=$d; ($a, $b) = @food; #$a and $b are the first two # items of @food. ($a, @somefood) = @food; # $a is the first item of @food # @somefood is a list of the # others. (@somefood, $a) = @food; # @somefood is @food and # $a is undefined. • To find the index of the last element of a list $#food#so lenght is $#food+1 • To display arrays print @food; # applespearseels print "@food"; # apples pears eels print @food.""; # 3
Summary of Array Functions sort(LIST) return a new list, the sorted from LIST reverse(LIST) return a new list, the reverse of LIST join(EXPR,LIST) return a string formed by concatenating each element of LIST joined by EXPR split(PATTERN,EXPR) return a list/array formed from each substring of EXPR bordered by PATTERN push(@ARRAY,LIST) add LIST to the end of @ARRAY pop(@ARRAY) remove and return the last element of @ARRAY unshift(@ARRAY,LIST) add LIST to the front of @ARRAY shift(@ARRAY) remove and return the first element of @ARRAY scalar(@ARRAY) return the number of elements in the array
Hashes (Associative Arrays) • Arrays elements of whichconsist of "key" and "value" pairs • Hash declarations: %map = (’red’,0xff0000, ’green’,0x00ff00, ’blue’,0x0000ff); or %map = (’red’=>0xff0000, ’green’=>0x00ff00, ’blue’=>0x0000ff); or %map = (); $map{red} = 0xff0000; $map{green} = 0x00ff00; $map{blue} = 0x0000ff; @arr = %map; # arr has 6 elements
Some Hash Functions keys(%HASH) Return a list of all the keys in %HASH. The list is "unordered" it depends on the hash function used internally. values(%HASH) Return a list of all the values in %HASH each(%HASH) Each time this is called on an %HASH, it will return a 2 element list consisting of the next key/value pair in the array. delete($HASH{KEY}) remove the pair associated with KEY from HASH.
Control Structures • if else if (EXPRESSION) { STATEMENTS; } elsif (EXPRESSION){ STATEMENTS; } else { STATEMENTS; } Note: curly braces are not optional in contrast to C. • unless unless (EXPRESSION) { STATEMENTS; } • while/do/until Loops while/until ( EXPRESSION ) { STATEMENTS; } do { STATEMENTS; } while/until ( EXPRESSION );
Control Structures (continued) • for loop for (INITIAL_EXPR ; COND_EXPR ; LOOP_EXPR ) { STATEMENTS; } • foreach loop foreach $tmp (@arr) { # do something with $tmp } • All loops support the following two control statements: • last : Declare that this is the last statement in the loop; completely exit the loop even if the condition is still true, ignoring all statements up to the loop's closing brace. • next : Start a new iteration of the loop
File Handling $file = '/etc/passwd';# Name the file open(INFO, $file); # Open the file @lines = <INFO>; # Read it into an array close(INFO); # Close the file print @lines; # Print the array • <> is line reading operator • If the filename was given in quotes then it is taken literally without shell expansion. To force shell expansion then use angled brackets. Use like <~/notes/todolist> open(INFO, $file); # Open for input open(INFO, ">$file"); # Open for output open(INFO, ">>$file"); # Open for appending open(INFO, "<$file"); # Also open for input
File Handling (continued) • To print a string to the file with the INFO filehandle use print INFO "This line goes to the file.\n"; • 3 predefined file handler STDIN, STDOUT, STDERR • To open the standard input (usually the keyboard) and standard output open(INFO, '-'); # Open standard input open(INFO, '>-'); # Open standard output chop($number=<STDIN>); #input number and remove newline chop($number=<>); #input number and remove newline Which means $number=<STDIN>; #input number chop($number); #remove newline print STDOUT “The number is $number. \n” #print the number
String Matching • One of the most useful features of Perl is its powerful string manipulation facilities. A regular expression is contained in slashes, and matching occurs with the =~ operator. The operator !~ is used for spotting a non-match $sentence =~ /the/ # expression is true if the string # “the” appearsin the variable $sentence !~ /the/ • The RE is case sensitive • if we assign the sentence to the special variable $_ which is of course a scalar: if (/under/) { print "We're talking about rugby\n"; }
String Matching (continued) • Here are some special RE characters and their meaning .# Any single character except a newline ^ # The beginning of the line or string $ # The end of the line or string * # Zero or more of the last character + # One or more of the last character ? # Zero or one of the last character [qjk]# Either q or j or k [^qjk]# Neither q nor j nor k [a-z] # Anything from a to z inclusive [^a-z] # No lower case letters [a-zA-Z] # Any letter [a-z]+ # Any non-zero sequence of lower case letters jelly|cream # Either jelly or cream (eg|le)gs # Either eggs or legs (da)+ # Either da or dada or dadada or... .*?: # It stops at first colon
Substitution and Translation • Perl can make substitutions based on matches $sentence =~ s/london/London/ # To replace an occurrence of # london by London in the string s/london/London/ # To do the same thing with the # $_ variable s/[Ll][Oo][Nn][Dd][Oo][Nn]/London/g # To make global substitution s/london/London/gi # an easier way is to use the i # option (for "ignore case"). $sentence =~ tr/abc/edf/ # tr function allows character- # by-character translation tr/a-z/A-Z/; # This statement converts $_ to # upper case
Split The split function is used like this: $info = "Caine:Michael:Actor:14, Leafy Drive"; @personal = split(/:/, $info); which has the same overall effect as @personal = ("Caine", "Michael", "Actor", "14, Leafy Drive"); If we have the information stored in the $_ variable then we can just use this instead @personal = split(/:/); @chars = split(//, $word); @words = split(/ /, $sentence); @sentences = split(/\./, $paragraph);
Subroutines sub printargs { print "@_\n"; } &printargs("perly", "king"); # Example prints perlyking &printargs("frog", "and", "toad"); # Prints "frog and toad" sub printfirsttwo { print "Your first argument was $_[0]\n"; print "and $_[1] was your second\n"; } • indexed scalars $_[0], $_[1] and so on have nothing to with the scalar $_ • Result of a subroutine is always the last thing evaluated sub maximum { if ($_[0] > $_[1]) { $_[0]; } else { $_[1]; } } $biggest = &maximum(37, 24); # Now $biggest is 37
Example 1 • Finds users whose accounts were locked in a linux computer. open(FD,"/etc/shadow"); @users=<FD>; foreach $elem (@users) { ($user,$passwdfield)=split(/:/,$elem); if ($passwdfield =~ /^!/){ print $user."\n"; } } • Finds users whose accounts were locked in a Solaris computer open(FD,"/etc/shadow"); @users=<FD>; foreach $elem (@users) { ($user,$passwdfield)=split(/:/,$elem); if ($passwdfield eq "*LK*"){ print $user."\n"; } }
Example 2 • Finds words in the dictionary file /usr/dict/words that consists of only asdfjghjkl letters open(fd,"/usr/dict/words"); while($line=<fd>){ if ($line =~ /^[asdfjklgh]+$/) {print $line;} }
Example 3 • Counts # of lines , # of sentences, # of nonwhitespace chars and determines which word is used how many times in the file whose name is given as parameter or in the text which is input from stdin if no parameter is given. @text=<>; foreach $sentence (@text){ $sentencecount++; @words=split(/\s/,$sentence); foreach $word (@words){ $myhash{$word}++; $wordcount++; @chars=split(//,$word); $charcount+=scalar(@chars); } } print "Total Number of Lines: $sentencecount\n"; print "Total Number of Words: $wordcount\n"; print "Total Number of Nonwhitespace chars: $charcount\n"; foreach $word (sort keys %myhash){ print "$word: $myhash{$word}\n"; }
Example 4 open(FD,"/var/mail/basarabu") or die "No inbox"; while (<FD>) { print if /^From:/ ;} close FD; open(FD,"/var/mail/basarabu") or die "No inbox"; while (<FD>) { print "$1\n" if /^From:(.+)/ ;} close FD; open(FD,"/var/mail/basarabu") or die "No inbox"; while (<FD>) { next unless /^From:(.+)/; next if $seen{$1}; print "$1\n"; $seen{$1}=1; } close FD;
Perl Socket Programming • Perl socket functions have the same names as the corresponding system calls in C. • Arguments tend to differ for two reasons: • Perl filehandles work differently than C file descriptors • Perl already knows the length of its strings • A sample TCP client using Internet-domain sockets: use strict; use Socket; my ($remote,$port, $iaddr, $paddr, $proto, $line); $remote = shift || 'localhost'; $port = shift || 2345; # random port $iaddr = inet_aton($remote) || die "no host: $remote"; $paddr = sockaddr_in($port, $iaddr); $proto = getprotobyname('tcp'); socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; connect(SOCK, $paddr) || die "connect: $!"; while (defined($line = <SOCK>)) { print $line; } close (SOCK) || die "close: $!"; exit;
A Corresponding Server use strict; use Socket; use Carp; $EOL = "\015\012"; # carriage return followed by new line sub logmsg { print ”$_[0] at ", scalar localtime, "\n" } my $port = shift || 2345; my $proto = getprotobyname('tcp'); socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l",1)) || die "setsockopt:$!"; bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!"; listen(Server,SOMAXCONN) || die "listen: $!"; logmsg "server started on port $port"; my $paddr; for ( ; $paddr = accept(Client,Server); close Client) { my($port, $iaddr) = sockaddr_in($paddr); my $name = gethostbyaddr($iaddr,AF_INET); logmsg "connection from $name [", inet_ntoa($iaddr), "] at port $port"; print Client "Hello there, $name, it's now ", scalar localtime, $EOL; }
Multithreaded Server use strict; use Socket; use Carp; $EOL = "\015\012"; sub spawn; # forward declaration sub logmsg { print "@_ at ", scalar localtime, "\n" } my $port = shift || 2345; my $proto = getprotobyname('tcp'); socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) || die "setsockopt: $!"; bind(Server, sockaddr_in($port, INADDR_ANY)) || die "bind: $!"; listen(Server,SOMAXCONN) || die "listen: $!"; logmsg "server started on port $port"; my $waitedpid = 0; my $paddr;
Multithreaded Server (cont. I) sub REAPER { $waitedpid = wait; $SIG{CHLD} = \&REAPER; # loathe sysV logmsg "reaped $waitedpid"; } $SIG{CHLD} = \&REAPER; for ( $waitedpid = 0; ($paddr = accept(Client,Server)) || $waitedpid; $waitedpid = 0, close Client) { next if $waitedpid and not $paddr; my($port,$iaddr) = sockaddr_in($paddr); my $name = gethostbyaddr($iaddr,AF_INET); logmsg “Conn. from $name [", inet_ntoa($iaddr), "] at port$port"; spawn; }
Multithreaded Server (cont. II) sub spawn { my $coderef = shift; unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') { confess "usage: spawn CODEREF"; } my $pid; if (!defined($pid = fork)) { logmsg "cannot fork: $!"; return; } elsif ($pid) { logmsg "begat $pid"; return; # I'm the parent } # else I'm the child -- go spawn open(STDIN, "<&Client") || die "can't dup client to stdin"; open(STDOUT, ">&Client") || die "can't dup client to stdout"; print "Hello there, $name, it's now ", scalarlocaltime, $EOL; exec '/usr/games/myGame’ or confess "can't exec the game: $!"; exit; }
ASample Unix-domain Client #!/usr/bin/perl -w use Socket; use strict; my ($rendezvous, $line); $rendezvous = shift || '/tmp/catsock'; socket(SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; connect(SOCK, sockaddr_un($rendezvous)) || die "connect: $!"; while (defined($line = <SOCK>)) { print $line; } exit;
A Corresponding Server use strict; use Socket; use Carp; sub logmsg { print "@_ at ", scalar localtime, "\n" } my $NAME = '/tmp/catsock'; my $uaddr = sockaddr_un($NAME); my $proto = getprotobyname('tcp'); socket(Server,PF_UNIX,SOCK_STREAM,0) || die "socket: $!"; unlink($NAME); bind (Server, $uaddr) || die "bind: $!"; listen(Server,SOMAXCONN) || die "listen: $!"; logmsg "server started on $NAME"; my $waitedpid; sub REAPER { $waitedpid = wait; $SIG{CHLD} = \&REAPER; logmsg "reaped $waitedpid”; }
Corresponding Server (cont.) $SIG{CHLD} = \&REAPER; for ( $waitedpid = 0; accept(Client,Server) || $waitedpid; $waitedpid = 0, close Client) { next if $waitedpid; logmsg "connection on $NAME"; spawn sub { print "Hello there, it's now ", scalar localtime, "\n"; exec '/usr/games/myGame' or die "can't exec myGame: $!"; }; }
Object-Oriented Network Programming • Some basic modules: • IO::Socket • IO::Socket::INET, IO::Socket::UNIX • Net::Inet • Net::FTP • Net::TCP • Net::UDP • Net::Telnet • Net::DNS
IO::Socket • Built upon the IO interface and inherits all the methods defined by IO • Only defines methods for those operations which are common to all types of socket • Operations which are specific to a socket in a particular domain have methods defined in sub classes of IO::Socket • Methods: • accept([PKG]) • timeout([VAL]) • Set or get the timeout value associated with this socket • sockopt(OPT [, VAL]) • If called with one argument then getsockopt is called, otherwise setsockopt is called • sockdomain • Returns the numerical number for the socket domain type • socktype • Returns the numerical number for the socket type • protocol • Returns the numerical number for the protocol being used on the socket, if known
IO::Socket::INET • Object interface for AF_INET domain sockets • Built upon the IO interface and inherits all the methods defined by IO • key-value pairs accepted by construtor: • PeerAddr Remote host address <hostname>[:<port>] • PeerPort Remote port or service<service>[(<no>)] | <no> • LocalAddr Local host bind address • LocalPortLocal host bind port • ProtoProtocol name (or number) "tcp" | "udp" | ... • Type Socket type SOCK_STREAM | SOCK_DGRAM |.. • ListenQueue size for listen • Reuse Set SO_REUSEADDR before binding • Timeout Timeout value for various operations • MultiHomed Try all addresses for multi-homed hosts
IO::Socket::INET (cont.) • Examples: • $sock = IO::Socket::INET->new( PeerAddr => 'www.perl.org', PeerPort => 'http(80)', Proto => 'tcp‘ ); • $sock = IO::Socket::INET->new(PeerAddr => 'localhost:smtp(25)'); • $sock = IO::Socket::INET->new( Listen => 5, LocalAddr => 'localhost', LocalPort => 9000, Proto => 'tcp‘ ); • $sock = IO::Socket::INET->new(’www.boun.edu.tr:80');
IO::Socket::Unix • Object interface for AF_UNIX domain sockets • key-value pairs accepted by construtor: • Type Type of socket (eg SOCK_STREAM or SOCK_DGRAM) • Local Path to local fifo • Peer Path to peer fifo • Listen Create a listen socket • Methods: • hostpath() • Returns the pathname to the fifo at the local end • peerpath() • Returns the pathanme to the fifo at the peer end
Net::Inet • Provides basic services for handling socket-based communications for the Internet protocol • Public Methods: • new • $obj = new Net::Inet; • $obj = new Net::Inet $host, $service; • $obj = new Net::Inet \%parameters; • $obj = new Net::Inet $host, $service, \%parameters; • init • return undef unless $self->init; • return undef unless $self->init(\%parameters); • return undef unless $self->init($host, $service); • return undef unless $self->init($host, $service, \%parameters); • bind • $ok = $obj->bind; • $ok = $obj->bind($host, $service); • $ok = $obj->bind($host, $service, \%parameters);
Net::Inet (cont. I) • unbind • $obj->unbind; • connect • $ok = $obj->connect; • $ok = $obj->connect($host, $service); • $ok = $obj->connect($host, $service, \%parameters); • format_addr • $string = $obj->format_addr($sockaddr); • $string = $obj->format_addr($sockaddr, $numeric_only); • format_local_addr, format_remote_addr • $string = $obj->format_local_addr; • $string = $obj->format_local_addr($numeric_only); • $string = $obj->format_remote_addr;
Net::Inet (cont. II) • Non-Method Subroutines: • inet_atonreturns the packed AF_INET address in network order • $in_addr = inet_aton('192.0.2.1'); • inet_addra synonym for inet_aton() • inet_ntoareturns the ASCII representation of the AF_INET address provided • $addr_string = inet_ntoa($in_addr); • htonl, htons, ntohl, ntohs • pack_sockaddr_in returns the packed struct sockaddr_in • $connect_address = pack_sockaddr_in($family, $port, $in_addr); • $connect_address = pack_sockaddr_in($port, $in_addr); • unpack_sockaddr_in returns the address family, port, and packed struct in_addr • ($family, $port, $in_addr) = unpack_sockaddr_in($connected_address);
Net::FTP • FTP Client class • Methods: • new (HOST [,OPTIONS]) • Options are: Firewall, Port, Timeout, Debug, Passive • login ([LOGIN [,PASSWORD [, ACCOUNT] ] ]) • type (TYPE [, ARGS]) • ascii ([ARGS]) binary([ARGS]) • rename ( OLDNAME, NEWNAME ) • delete ( FILENAME ) • cwd ( [ DIR ] ) • cdup () • pwd () • rmdir ( DIR ) • mkdir ( DIR [, RECURSE ]) • get ( REMOTE_FILE [, LOCAL_FILE [, WHERE]] )
Net::FTP (cont. I) • put ( LOCAL_FILE [, REMOTE_FILE ] ) • append ( LOCAL_FILE [, REMOTE_FILE ] ) • mdtm ( FILE ) • modification time of a file • size ( FILE ) • supported ( CMD ) • pasv () • pasv_xfer ( SRC_FILE, DEST_SERVER [, DEST_FILE ] ) • do a file transfer between two remote ftp servers • pasv_wait ( NON_PASV_SERVER ) • wait for a transfer to complete between a passive server and a non-passive server • abort () • quit ()
Net::FTP (cont. II) • Example: use Net::FTP; $ftp = Net::FTP->new(”ftp.boun.edu.tr"); $ftp->login("anonymous","me@boun.edu.tr"); $ftp->cwd("/pub"); $ftp->get("the.file"); $ftp->quit;