420 likes | 522 Views
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.
E N D
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 side close $client; #disconnect client from server close $server; #close server connection
IO::Socket Server Example #!/usr/bin/perl use 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/perl use 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/perl use 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 use socket(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 part setsockopt (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 socket bind(SERVER, $my_addr); Establish listen queue for connections listen(SERVER, SOMAXCONN); SOMAXCONN is the max connection allowed in queue, before I used 10.
Socket Server(3) Now wait for a connection accept(CLIENT, SERVER); Use CLIENT as the FILEHANDLE close server connection close SERVER;
Socket Server example #!/usr/bin/perl use 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/perl use 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/perl use 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, LENGTH number 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/perl use 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/perl use 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. Will also install doc into the activePerl doc's
http module use 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 modules print $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/perl use 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 loop print "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/perl use 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 line while (<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 DBI use DBI; #command to load it into perl • Now we need to connection to our database my $dbh = DBI->connect( "dbi:mysql:database=YOURDATABASE", 'USERNAME','PASSWORD'); • $dbh is an object used to talk to the database after a successful connection.
Connection Example my $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::errstr print "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::NetResource manage 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
Q A &