Perl

Post on 05-Jan-2016

15 views 0 download

description

Server side networking and modules. Perl. Server Side networking. Uses same modules. Instead connection to something, the server side will listen for the incoming connection. IO::Socket Server. - PowerPoint PPT Presentation

Transcript of Perl

Perl

Server side networking and modules

Server Side networking

• Uses same modules.—Instead connection to something, the server

side will listen for the incoming connection.

IO::Socket Server

$server = IO::Socket::INET->new (LocalPort =>$server_port, Type => SOCK_STREAM, Reuse=> 1, Listen => 10)

or die "Couldn't open port $server_port: $@\n";—LocalPort => $server_port

– Where $server_port is the port number the server will use

—Reuse => 1– Reuse the port, so the server can reuse the port,

instead of waiting two minutes for the O/S to release the port

—Listen =>10– Where 10 is the number O/S how many unanswered

connections to queue up waiting for you server. SOMAXCONN is the max connection the O/S will allow.

IO::Socket Server (2)

• Now the server waits for a connection• Use the accept function$client = $server->accept();

• After the client connection is established use $client like FILEHANDLE

• to close the server sideclose $client; #disconnect client from serverclose $server; #close server connection

IO::Socket Server Example#!/usr/bin/perluse IO::Socket;

$server_port = 3012;$server = IO::Socket::INET->new (LocalPort => $server_port, Type => SOCK_STREAM, Reuse=> 1, Listen => 10)

or die "Couldn't open port $server_port: $@\n";

$client = $server->accept(); $line = <$client>;print "$line \n";print $client "Hi back \n";close $client; close $server;

IO::Socket Server Example (client side)#!/usr/bin/perluse IO::Socket;$remote_host = "localhost";$remote_port = "3012";$socket = IO::Socket::INET->new (PeerAddr => $remote_host, PeerPort => $remote_port, Proto => "tcp", Type => SOCK_STREAM) or die "Couldn't connect to $remove_host:$remote_port : $@\n";

print $socket "Hi\n"; $answer = <$socket>;print "$answer \n";close $socket;

IO::Socket Server Example for multiple connections#!/usr/bin/perluse IO::Socket;

$server_port = 3012;$server = IO::Socket::INET->new (LocalPort =>

$server_port, Type => SOCK_STREAM, Reuse=> 1, Listen => 10)

or die "Couldn't open port $server_port: $@\n";

while($client = $server->accept() ) {#answer each connection, then disconnects clients,

and answers next connection$line = <$client>;print "$line \n";print $client "Hi back \n";close $client;

}close $server;

Socket Server

• Again more complex and multi stepped.• create a socket to usesocket(SERVER, PF_INET, SOCK_STREAM,

getprotobyname('tcp'));—SERVER is the HANDLE—PF_INET the domain type, with IO::Socket it was part of

the new call.—getprotobyname('tcp') get the O/S number for tcp

– should allows use this function, since the number has been known to change and for portability issues.

—NOTE: should allows use the constants, instead of the number equivalent, because these number have been known to change (on a whim) and portability between versions of the same O/S become an issue.

Socket Server(2)

• Setup the Reuse partsetsockopt (SERVER, SOL_SOCKET, SO_REUSEADDR, 1);

• Next build up my socket address$my_addr = sockaddr_in($server_port,

INADDR_ANY);—INADDR_ANY allows clients to from anywhere

• Next bind to the socketbind(SERVER, $my_addr);• Establish listen queue for connectionslisten(SERVER, SOMAXCONN);

—SOMAXCONN is the max connection allowed in queue, before I used 10.

Socket Server(3)

• Now wait for a connectionaccept(CLIENT, SERVER);

• Use CLIENT as the FILEHANDLE

• close server connectionclose SERVER;

Socket Server example#!/usr/bin/perluse Socket;use IO::Handle;

$remote_port = 3012;socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp'));SERVER->autoflush(1); #socket doesn't have autoflush turned on.setsockopt (SERVER, SOL_SOCKET, SO_REUSEADDR, 1);

$my_addr = sockaddr_in($remote_port, INADDR_ANY);bind (SERVER, $my_addr) or die "can't bind$!\n";

listen(SERVER, SOMAXCONN) or die "Can't listen to port $! \n";

accept (CLIENT, SERVER);CLIENT->autoflush(1); #socket doesn't have autoflush turned on.

$answer = <CLIENT>;print "$answer \n";print CLIENT "Hi back \n";close CLIENT;close SERVER;

Socket Server example client side#/usr/bin/perluse Socket;use IO::Handle;

$remote_host = "localhost";$remote_port = 3012;socket(SERVER, PF_INET, SOCK_STREAM,

getprotobyname('tcp'));SERVER->autoflush(1); #socket doesn't have autoflush

turned on.$internet_addr = inet_aton($remote_host) or die "Can't

convert $!\n"; $paddr = sockaddr_in($remote_port, $internet_addr);print "Attempting to connect :$paddr:\n";connect (SERVER, $paddr) or die "can't connect $!\n";

print SERVER "Hi\n"; $answer = <SERVER>;print "$answer \n";close SERVER;

Socket Server for multiple connections#!/usr/bin/perluse Socket;use IO::Handle;

$remote_port = 3012;socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp'));SERVER->autoflush(1); #socket doesn't have autoflush turned on.setsockopt (SERVER, SOL_SOCKET, SO_REUSEADDR, 1);

$my_addr = sockaddr_in($remote_port, INADDR_ANY);bind (SERVER, $my_addr) or die "can't bind$!\n";

listen(SERVER, SOMAXCONN) or die "Can't listen to port $! \n";

while (accept (CLIENT, SERVER)) { CLIENT->autoflush(1); #socket doesn't have autoflush turned on. $answer = <CLIENT>; print "$answer \n"; print CLIENT "Hi back \n"; close CLIENT;}close SERVER;

Exercise 14

• Create a server. It should connect and than wait for a message "Connection from NAME"

• It should then response "Hi NAME"

• Listen on port 3012

• Change your client process to connect to localhost, to test your server. (you'll need two dos windows. One for the server, one for the client.

read and sysread

• When you need to read only a specified number bytes, you can use read or sysread, instead of <HANDLE>.

number of bytes read = sysread HANDLE, SCALAR, LENGTHnumber of bytes read = read HANDLE, SCALAR, LENGTH

—basically the same function

—NOTE: ignores all end of line markers, and read the number bytes listed or until "end of file"

• $x = read SERVER, $answer, 100—read from SERVER handle, place 100 bytes of

data into $answer. $x contains number of bytes read.

read example#/usr/bin/perluse Socket;use IO::Handle;

$remote_host = "k2.cs.uwyo.edu";$remote_port = 80;socket(Server, PF_INET, SOCK_STREAM, getprotobyname('tcp'));Server->autoflush(1); #socket doesn't have autoflush turned on.$internet_addr = inet_aton($remote_host) or die "no convert $!\n"; $paddr = sockaddr_in($remote_port, $internet_addr);connect (Server, $paddr) or die "can't connect $!\n";

print Server "GET / HTTP/1.0\n\n";while ($x = read(Server,$answer,100) ) {

last if $x <100; print "$x:Still reading 100 bytes at a time\n";print "$answer\n";

}print "$x: Last line:\n";print "$answer \n";

close Server;

syswrite

• To write a specified number of bytes, you can use syswrite—NOT write, used for formatting. There is no

"opposite" of read.• Number of bytes written = syswrite HANDLE, SCALAR,

LENGTH

• $x = syswrite Server, $line, 25—write 25 bytes of $line to Server. $x contains the

number of bytes actually written—$x can equal 0, if $line is empty.—$x = undef if there was an error.

send and recv functions

• similar to <HANDLE> and print HANDLE• Socket use:

—send(SERVER, $data_to_send, $flags)– send(SERVER, "Hi there\n", 0);

—recv(SERVER, $data_read, $max_len, $flags)– recv(SERVER, $answer, 100, 0);

• IO::Socket use:—$socket->send($data_to_send, $flags)

– $socket->send("Hi there\n", 0);

—$socket->recv($data_read, $flags)– $socket->recv($answer,0);

Server with process concurrency#!/usr/bin/perluse IO::Socket;$server_port = 3012;$server = IO::Socket::INET->new (LocalPort => $server_port, Type

=> SOCK_STREAM, Reuse=> 1, Listen => 10) or die "Couldn't open port $server_port: $@\n";

while($client = $server->accept() ) { if ($pid = fork) { # Parent process next; #go back and accept the next connection } else { unless (defined $pid) {die "Can't fork: $! \n";} #child process $line = <$client>;

print "$line \n"; print $client "Hi back \n"; close $client;

exit; }}close $server;

Closing sockets after forks

• close won't always send the EOF or SIGPIPE after a fork, unless all processes close.

• So, you use shutdown instead.—Socket:—shutdown(SOCKET,0);# I have stopped

reading.—shutdown(SOCKET,1);#I have stopped writing.—shutdown(SOCKET,2);#I have stopped using

this—IO::Socket—$socket->shutdown(0); #stopped reading

– etc…

Modules

• depending on your perl, there may be any number of modules that are built-in. —ActivePerl includes a number of modules that

the standard perl doesn't include. See doc's

• There are thousands of modules can be added to perl—http://www.cpan.org/

– you can find and download modules.

—for ActivePerl– use perl package manager (found on the start menu,

under active perl) once you know what modules you want to install. (see ActivePerl doc's for more help)

+ search <module name> #returns a numbered list of modules matching the queary,

+ install number #where number is from the search list.o Will also install doc into the activePerl doc's

http moduleuse Net::HTTP;my $s = Net::HTTP->new(Host => "asuwlink.uwyo.edu")

|| die $@;

$s->write_request(GET => "/", 'User-Agent' => "Mozilla/5.0");

my($code, $mess, %h) = $s->read_response_headers;

while (1) { my $buf; my $n = $s->read_entity_body($buf, 1024); last unless $n; print $buf; }

CGI module

• for CGI scripts (ie web programming)#!/usr/bin/perl use CGI;my $cgi = new CGI;

#reading parameters from a from$x = $cgi->param('X'); #where X is the

name$y = $cgi->param('Y);

CGI module (2)

• create web pages• you can a normal print statements or the

functions provided by CGI modulesprint $cgi->header;

—html header needed by the browsers

print "hello World\n";—STDOUT is redirected to the browsers

print $cgi->h1("Hello World");—print "<h1>Hello World</h1>\n";

print $cgi->hr;see the CGI manpages or perldoc for more.

CGI module (3)

• you can run perl cgi scripts from the command line and type in parameters.—This allows you test the scripts without a web

server and browser—Some versions of the CGI module it will stop

and wait for parameters– for parameters: name=value– then control-D (UNIX)/control-z (windows)

—Newer versions will process parameters as part of the command line arguments.

– To change to wait for parameters – use CGI "-debug"; #after you debugged the script,

remove the "-debug"

ftp module

use Net::FTP;$ftp = Net::FTP->new(ftpsite);$ftp->login(username,password);$ftp->binary; #set to binary transfer$ftp->hash(true); #turn on hashing$ftp->get(FILENAME); #get filename (can include

directory as well—file is put in current working directory

@files = $ftp->ls(); #a directory or filename can be include inside the ().

$ftp->quit; #close ftp connection• all of these return true/false values, the next slide

is an ftp site to get updates for RedHat linux

FTP script example (getfile.pl)#!/usr/bin/perl$file = $ARGV[0]; $todir = $ARGV[1];use Net::FTP;@toget = ();$ftpsite = "updates.redhat.com";while(1) { if ($ftp = Net::FTP->new($ftpsite)) { if ($ftp->login("anonymous","seker\@k2.cs.uwyo.edu") ) { $ftp->binary; $ftp->hash(true); $f = $todir.$file; if ($ftp->get($f)) { print "yes\n"; last; } else { print "no!, Trying again.\n"; } } else { print "anonymous connection denied.\n"; $ftp->quit; redo; } } else { print "Not able to connect to $ftpsite\n"; sleep(10); }}

another FTP script example (getallfiles.pl)#!/usr/bin/perluse Net::FTP;$ftpsite = "updates.redhat.com";@dir = ("/8.0/en/os/i386/",

"/8.0/en/os/noarch/", "/8.0/en/os/i686/");foreach $todir (@dir) {while(1) { if ($ftp = Net::FTP->new($ftpsite)) { if ($ftp->login("anonymous","seker\

@k2.cs.uwyo.edu") ) { $ftp->binary; $ftp->hash(true); print "In, changeing directories\n"; $ftp->cwd($todir); print "In, getting list\n"; @toget = $ftp->ls(); print "Done.\n"; $ftp->quit; last; } else { print "anonymous connection

denied.\n"; $ftp->quit; redo; } } else { print "Not able to connect to

$ftpsite\n"; sleep(10); }}

print "Getting new rpms\n";$i = $#toget;foreach $file (@toget) { if ( -e "$file") { --$i; next; } print "getting $file in $todir\n"; $x = system("getfile.pl $file $todir"); --$i;}}#end of foreach loopprint "Finished \n";

• This scripts functions to lists all the files in the @dir array, found out they have already been downloaded. If they haven't, then call getfile.pl script to get each file.

• The reason for the second script timeout of a ftp session will cause the script to terminate.

• All files are downloaded to the current working directory.

STMP module

use Net::SMTP; #for sending e-mail.use Sys::Hostname; #for hostname command (next

line)$smtp = Net::SMTP->new(hostname);$smtp->mail("seker\@uwyo.edu"); #from$smtp->recipient("username\@somewhere");#

mail to$smtp->data(); #start of mail data$smtp->datasend("Subject: Whatever");

—for the subject line

$smtp->datasend("\n\n"); # end of mail headers $smtp->datasend("bah.. bah… bah…\n");

—what ever you want to say, use as many times as needed.

$smtp->dataend(); #end of mail message$smtp->quit(); #sends the e-mail.

SMTP example#!/usr/local/bin/perluse Net::SMTP; use Sys::Hostname;open FP, "grading2150.csv";

#header line creation.#header line is created here, but

left out for space reasons.#read each students grade, then e-

mail with header linewhile (<FP>) { chop;chop; #get rid of eol

marker, and windws eol marker @list = split ',';# create name and e-mail, plus some

clean up $f =lc $list[0]; $l = lc $list[1]; $name = "\u$f,\u$l"; $name =~ s/\"//g; $emails = $list[$#list]; $emails =~ tr/A-Z/a-z/; $emails =~ s/\"//g;

if ($emails ne "") {# put together grade variable here, again

left out $hostname = hostname; $smtp = Net::SMTP->new($hostname); $smtp->mail("seker\@uwyo.edu"); #from

line $smtp->recipient($emails); #to line

$smtp->data(); #start data $smtp->datasend("Subject: Course

grades\n"); #subject line $smtp->datasend(""); #line to

separate header lines from body of the test.

$smtp->datasend("\n\nName: $name\n"); $smtp->datasend("$head\n"); $smtp->datasend("$grade\n"); $smtp->datasend("\n"); $smtp->dataend(); $smtp->quit(); } else {

print "no e-mail for $name \n"; }}

Perl, ODBC, and MYSQL

• The ODBC modules can be added to perl from http://www.cpan.org for just about any database you want to connect to.

• The MYSQL modules were added as of redhat 9 distribution and mysql, so I going to use them for this.

Connection to MYSQL

• First we need the module called DBIuse DBI; #command to load it into perl• Now we need to connection to our

databasemy $dbh = DBI-

>connect( "dbi:mysql:database=YOURDATABASE", 'USERNAME','PASSWORD');

• $dbh is an object used to talk to the database after a successful connection.

Connection Examplemy $dbh = DBI->connect("

dbi:mysql:database=webacc", 'test','csteach');

unless($dbh) { #make sure a connection was made,

otherwise #exit warn "Unable to connect to mysql

($DBI::errstr)\n"; exit 0;}• $DBI::errstr will tell you the error

received.

accessing the database

• Once connected, we can create SQL statements to list, update, insert, delete data in the database.

• There are two different functions depending on whether there is data coming back (say a SELECT) or not.

Using a SQL Select statement• We also need a second variable to hold the data.

—I have a habit of using $sth, but the name is not relevant.

• First the sql statement needs to be created$sql = 'SELECT * FROM test ';• Now we need to prepare and execute the

statement$sth=$dbh->prepare($sql);$sth->execute;• After that we are ready to read in the data• Uses $sth->fetchrow, which brings back one row

at a time, using an array from the fields@arr = $sth->fetchrow;

Using a SQL Select statement (2)• Generally speaking fetchrow is done with

a loop, so you don't have know how many rows are returned.

while (@arr = $sth->fetchrow) { #then deal with each row. fields in @arr}• Lastly we need to tell the database we are

done with this query.$sth->finish;

Other commands

• SQL commands where there is no data coming back, say an insert, update, or delete, the commands are simpler.

$sql = "delete from test where name='k2' ";• Execute the statement$dbh->do($sql);• If there was an error, we can use

$DBI::errstrprint "problem: ($DBI::errstr)\n";

References

• There is a lot more to the DBI, which you can look up if you are interested

• reference: (official guide)

Programming the Perl DBI, Descartes and Bunce, O'Reilly, 2000

Other modules

• XML modules• database ODBC modules• TK modules (included in ActivePerl)

—for scripts with GUI interfaces

• numerous ones for File I/O and reading/writing file types, such as image files, even MS office documents.

• everything from audio and video modules to a networking, such telnet to a cisco router and ssh.

• See www.cpan.org for the module list.

Windows Win32 module• The win32 module and it extensions allow access

to the windows O/S system• The following lists just some of the functionality

of the win32 module and extensions—Win32::GetOSName()

– returns undef, Win32s, Win95, Win98, WinMe, Win2000, WinXP/.Net, WinNT3.51, or WinNT4

—Win32::MsgBox(MESSAGE [, FLAGS [, TITLE]])– Create a dialogbox containing MESSAGE, see doc for more

info.—Win32::InitiateSystemShutdown(MACHINE, MESSAGE,

TIMEOUT, FORCECLOSE, REBOOT)– initiate a system shutdown or reboot.

—Win32::LoginName– return username of owner of the current perl process

—Win32::NodeName– Returns node name of current windows machine

—use Win32::Process– access process creation and management, including

functions for kill, suspend, resume and priorities of process

Windows Win32 module (2)—use win32::AuthenticateUser

– user authentications for domains

—use Win32::TieRegistry– Powerful and easy ways to manipulate a registry

—use Win32::Netadmin– manage network groups and users

—use Win32::NetResourcemanage network resources

—use Win32::EventLog – process the eventlog

—use Win32::Internet– use windows to access http, ftp, and gopher connections

—use Win32::Service– manage system services

—use Win32::Sound– An extension to play with Windows sounds

QA&