<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Effective Perler &#187; networking</title>
	<atom:link href="http://www.effectiveperlprogramming.com/blog/category/book/new-chapters/networking/feed" rel="self" type="application/rss+xml" />
	<link>http://www.effectiveperlprogramming.com</link>
	<description>Effective Perl Programming - write better, more idiomatic Perl</description>
	<lastBuildDate>Sat, 28 Jan 2012 02:19:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Know when and when not to write networking code.</title>
		<link>http://www.effectiveperlprogramming.com/blog/154</link>
		<comments>http://www.effectiveperlprogramming.com/blog/154#comments</comments>
		<pubDate>Sun, 13 Jun 2010 04:38:19 +0000</pubDate>
		<dc:creator>Josh McAdams</dc:creator>
				<category><![CDATA[item]]></category>
		<category><![CDATA[networking]]></category>

		<guid isPermaLink="false">http://www.effectiveperlprogramming.com/?p=154</guid>
		<description><![CDATA[Even though Perl has support for low-level socket programming, that doesn&#8217;t mean that you have to program at the low-level. For common protocols such as FTP, HTTP, POP3, or SMTP, you can use modules that come with Perl to handle the transport details. libnet, the distribution that comprises the basic protocols, comes with Perl since [...]]]></description>
			<content:encoded><![CDATA[<p>Even though Perl has support for low-level socket programming, that doesn&#8217;t mean that you have to program at the low-level. For common protocols such as FTP, HTTP, POP3, or SMTP, you can use modules that come with Perl to handle the transport details. <a href="http://search.cpan.org/dist/libnet">libnet</a>, the distribution that comprises the basic protocols, comes with Perl since 5.8. Many other protocols, such as SSH, have implementations on CPAN. You can also install from CPAN many higher level libraries, such as <a href="http://search.cpan.org/dist/libwww-perl">LWP</a> and <a href="http://search.cpan.org/dist/WWW-Mechanize">WWW::Mechanize</a>.</p>
<p>There are several reasons to avoid as much low-level work as you can. The foremost reason is that widely-used and heavily-tested libraries have not already made all of the mistakes that you are bound to make, but they&#8217;ve almost certainly fixed them. They probably handle all of the edge cases that you don&#8217;t even know about, so when your architecture changes, those widely-used modules easily handle the new setup. Is your hand-rolled code to talk to a remote server going to easily handle a proxy or SOCKS setup, or be able to switch from an unencrypted channel to SSL? </p>
<p>Unless you&#8217;re the sort of person who likes working in the low-level details, you&#8217;re simply wasting your time be reinventing the wheel. If you think your wheel is amazingly better, but you have to remember a lot of people think that. If you have the energy, consider contributing to your enthusiasm to the existing CPAN libraries.</p>
<p>As with everything in <i>The Effective Perl</i>, this isn&#8217;t a hard and fast rule. For some things, the higher level libraries don&#8217;t give you full access to the protocol, so you do need to work at a lower level.</p>
<p>Enough of that. You may still need some examples. These give you the flavor of what&#8217;s available, but that doesn&#8217;t mean they are appropriate for your particular situation. As with all modules, use them when they make sense and don&#8217;t use them when they don&#8217;t.</p>
<h2>Simple file downloading</h2>
<p><a href="http://search.cpan.org/dist/libwww-perl">LWP::Simple</a> can handle simple downloads for you:</p>
<pre class="brush:perl">
use LWP::Simple;
my $page = get( 'http://www.perlfoundation.org/' );
</pre>
<p>That&#8217;s simple enough, but what if you need to store that resource somewhere? There&#8217;s an app for that:</p>
<pre class="brush:perl">
use LWP::Simple;
getstore( 'http://www.perlfoundation.org/', 'tpf-index.html' );
</pre>
<p>This also works with FTP and many other protocols. <a href="http://search.cpan.org/dist/libwww-perl">LWP</a> actually handles many other protocols that you might not consider to be part of the World Wide Web. Perhaps you need to fetch some images from a NASA FTP server:</p>
<pre class="brush:perl">
use LWP::Simple;
getstore(
	'ftp://nssdcftp.gsfc.nasa.gov/photo_gallery/hi-res/planetary/moon/gal_moon_color.tiff',
	'awesome-moon.tiff'
	);
</pre>
<h2>Sending email</h2>
<p>There are many CPAN modules that can help you send email, and <a href="http://search.cpan.org/dist/Email-Send">Email::Send</a> is a general interface to many of them. In the constructor, you specify the implementor, in this case, <code>SMTP</code>, and the arguments to the implementor. <code>Email::Send</code> takes care of the rest:</p>
<pre class="brush:perl">
use Email::Send;

my $message = <<'EMAIL';
To: buster@example.com
From: me@example.com
Subject: I'm letting Email::Send send this

I did almost nothing to send this email.
EMAIL

my $sender = Email::Send->new({
	mailer      => 'SMTP',
	mailer_args => [ Host   => 'smtp.example.com' ],
	});

my $rc = $sender->send( $message );
unless( $rc ) {
	warn "Problem sending mail! $rc\n";
	}
else {
	print "Send mail just fine.\n";
	}
</pre>
<p>Unfortunately, <code>Email::Send</code> is superceded by <a href="http://search.cpan.org/dist/Email-Simple">Email::Simple</a>, but here&#8217;s the same program:</p>
<pre class="brush:perl">
use Email::Sender::Simple qw(sendmail);
use Email::Simple;
use Email::Simple::Creator; # an Email::Simple mixin
use Email::Sender::Transport::SMTP;

my $transport = Email::Sender::Transport::SMTP->new({
	host => 'smtp.example.com', # you can also set this in %ENV
	});

my $email = Email::Simple->create(
	header => [
		To      => '"Buster Bean" <buster@example.com>',
		From    => '"Mimi Bean" <mimi@example.com>',
		Subject => "Thanks for all the fish",
	],

	body => "I'm sending this with Email::Simple.\n",
	);

my $rc = eval { sendmail(
	$email,
	{ transport => $transport }
	) };

unless( $rc ) {
	warn "Problem sending mail! $@\n";
	}
else {
	print "Send mail just fine.\n";
	}
</pre>
<p>This &#8220;simpler&#8221; version is under active development, but it goes against most of the points we want to stress: you shouldn&#8217;t have to think about what most of this is doing or how email actually works, just like you don&#8217;t have to understand internal combustion to drive a car.</p>
<h2>Programmatic control of a web browser</h2>
<p><code>LWP</code> is sufficient for simple web tasks, but when you have to interact with forms, click through several pages, and handle other actions you might expect from an interactive browser, <a href="http://search.cpan.org/dist/WWW-Mechanize">WWW::Mechanize</a> is the tool you should you. It tracks your path through a website, handles cookies, and lets you select and follow links.</p>
<p>Here&#8217;s an example that takes a module name, a starting line number, and an ending line number. It goes through these steps:</p>
<ul>
<li>queries <a href="http://search.cpan.org/">CPAN Search</a> for the module,
<li>finds the right link in the search results</p>
<li>follows the module link
<li>looks for the &#8220;Source&#8221; link on that page
<li>gets the content of that page
<li>extract that line range
</ul>
<pre class="brush:perl">
use WWW::Mechanize;

my( $module, $start_line, $end_line ) = @ARGV;
print "Looking for $module lines $start_line to $end_line\n";

my $mech = WWW::Mechanize->new;

$mech->get( 'http://search.cpan.org' );

$mech->submit_form(
	form_number => 1,
	fields      => {
		query   => $module,
		mode    => 'module',
		}
	);

my $module_links_ref = $mech->find_link( text => $module )
	or die "Did not find $module link\n";
$mech->get( $module_links_ref->[0] );

$mech->follow_link( text_regex => qr/\ASource\z/ )

my $content = $mech->content;

open my( $fh ), '<', \ $content;

while( <$fh> ) {
	next unless $. == $start_line .. $. == $end_line;
	printf "%d: %s", $., $_;
	}
</pre>
<p>You can run this program to get an extract of some lines from <a href="http://search.cpan.org/dist/HTTP-Size">HTTP::Size</a>:</p>
<pre class="brush:perl">
$ perl mech HTTP::Size 10 20
Looking for HTTP::Size lines 10 to 20
10:
11: =head1 SYNOPSIS
12:
13:     use HTTP::Size
14:
15:     my $size = HTTP::Size::get_size( $url );
16:
17:     if( defined $size )
18:             {
19:             print "$url size was $size";
20:             }
</pre>
<p>This is only a small taste of the sorts of things that <code>WWW::Mechanize</code> can do.</p>
<h2>Downloading new files from an FTP server</h2>
<p>Sometimes you need to use a lower-level interface. For instance, if you want to sync a local directory with a remote FTP directory, you can use <a href="http://perldoc.perl.org/Net/FTP.html">Net::FTP</a> to connect to the remote directory, get the list of files in that directory, compare the modification time of the local file with the modification time, and download files that are newer on the remote side:</p>
<pre class="brush:perl">
use Net::FTP;

my $host = 'nssdcftp.gsfc.nasa.gov';

my $ftp = Net::FTP->new( $host, Debug => 0 )
	or die "Cannot connect to $host: $@";

$ftp->login("anonymous",'-anonymous@')
	or die "Cannot login: ", $ftp->message;

$ftp->cwd( '/photo_gallery/hi-res/planetary/moon' );

foreach my $file ( $ftp->ls ) {
	if( (stat($file))[9] < $ftp->mdtm( $file )  ) {
		print "Fetching $file...\n";
		$ftp->get( $file );
		}
	else {
		print "$file up-to-date\n";
		}

	}
</pre>
<p>In this case, the <code>Net::FTP</code> module is the appropriate level of coding. You don&#8217;t have to deal with the FTP protocol directly, but you have enough flexibility to deal with the features that the protocol provides.</p>
<h2>Low-level sockets</h2>
<p>Perl has the built-in interface so you can minutely control TCP and UDP sockets if that&#8217;s what you need to do. However, since we&#8217;re trying to convince you not to do that, we&#8217;ll leave those bits as an exercise for the reader.</p>
<h2>Things to remember</h2>
<ul>
<li>Work at the highest level possible and reasonable
<li>Use one of the popular CPAN modules instead of reinventing your own.
<li>Don&#8217;t create your own low-level implementations
</ul>
<p align="left"><a class="tt" href="http://twitter.com/home/?status=Know+when+and+when+not+to+write+networking+code.+http://tinyurl.com/66qlbha" title="Post to Twitter"><img class="nothumb" src="http://www.effectiveperlprogramming.com/wp-content/plugins/tweet-this/icons/tt-twitter2.png" alt="Post to Twitter" /></a> <a class="tt" href="http://twitter.com/home/?status=Know+when+and+when+not+to+write+networking+code.+http://tinyurl.com/66qlbha" title="Post to Twitter"> </a> <a class="tt" href="http://delicious.com/post?url=http://www.effectiveperlprogramming.com/blog/154&amp;title=Know+when+and+when+not+to+write+networking+code." title="Post to Delicious"><img class="nothumb" src="http://www.effectiveperlprogramming.com/wp-content/plugins/tweet-this/icons/tt-delicious.png" alt="Post to Delicious" /></a> <a class="tt" href="http://delicious.com/post?url=http://www.effectiveperlprogramming.com/blog/154&amp;title=Know+when+and+when+not+to+write+networking+code." title="Post to Delicious"> </a> <a class="tt" href="http://digg.com/submit?url=http://www.effectiveperlprogramming.com/blog/154&amp;title=Know+when+and+when+not+to+write+networking+code." title="Post to Digg"><img class="nothumb" src="http://www.effectiveperlprogramming.com/wp-content/plugins/tweet-this/icons/tt-digg.png" alt="Post to Digg" /></a> <a class="tt" href="http://digg.com/submit?url=http://www.effectiveperlprogramming.com/blog/154&amp;title=Know+when+and+when+not+to+write+networking+code." title="Post to Digg"> </a> <a class="tt" href="http://www.facebook.com/share.php?u=http://www.effectiveperlprogramming.com/blog/154&amp;t=Know+when+and+when+not+to+write+networking+code." title="Post to Facebook"><img class="nothumb" src="http://www.effectiveperlprogramming.com/wp-content/plugins/tweet-this/icons/tt-facebook.png" alt="Post to Facebook" /></a> <a class="tt" href="http://www.facebook.com/share.php?u=http://www.effectiveperlprogramming.com/blog/154&amp;t=Know+when+and+when+not+to+write+networking+code." title="Post to Facebook"> </a> <a class="tt" href="http://reddit.com/submit?url=http://www.effectiveperlprogramming.com/blog/154&amp;title=Know+when+and+when+not+to+write+networking+code." title="Post to Reddit"><img class="nothumb" src="http://www.effectiveperlprogramming.com/wp-content/plugins/tweet-this/icons/tt-reddit.png" alt="Post to Reddit" /></a> <a class="tt" href="http://reddit.com/submit?url=http://www.effectiveperlprogramming.com/blog/154&amp;title=Know+when+and+when+not+to+write+networking+code." title="Post to Reddit"> </a></p>]]></content:encoded>
			<wfw:commentRss>http://www.effectiveperlprogramming.com/blog/154/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

