ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/AnyEvent/doc/Tutorial.pod
Revision: 1.2
Committed: Sun May 25 14:35:53 2008 UTC (18 years, 4 months ago) by elmex
Branch: MAIN
Changes since 1.1: +130 -1 lines
Log Message:
further work on the tutorial

File Contents

# User Rev Content
1 elmex 1.1 =head1 Network Programming with AnyEvent
2    
3     This is a tutorial that will explain the usage of AnyEvent for
4     Network programming.
5    
6     =head2 Introduction
7    
8     AnyEvent is first of all just a framework for multiple event loops. It's a
9     thin abstraction layer above all kinds of event loops. It's main purpose is to
10     move the choice of the event loop (whether it should be Glib, Qt, EV or Event,
11     or even something else, see also L<AnyEvent>) from the module author to the
12     program author.
13    
14     The problem was usually that modules like L<Net::IRC> came with their own
15     event loop, where the program author needed to start the event loop
16     of L<Net::IRC>. That usually meant that he couldn't integrate it easily with
17     a L<Gtk2> GUI for instance.
18    
19     Another example is L<LWP>, it provides no event interface at all. It's a pure
20     blocking HTTP client library, which usually means that you either have to
21     start a thread or have to fork for a HTTP request, or use L<Coro::LWP>.
22    
23     L<AnyEvent> now does B<not> force authors of modules, like L<Net::IRC>, to:
24    
25     =over 4
26    
27     =item 1. Write their own event loop.
28    
29     =item 2. Choose one fixed event loop.
30    
31     =back
32    
33     If the module author uses L<AnyEvent> for all his event needs (IO events, timers,
34     signals, ...) all other modules can just use his module and don't have to choose
35     an event loop or adapt to his event loop. The choice of the event loop is ultimately
36     made by the program author who uses all the modules and writes the main
37     program. And even there he doesn't have to choose, he can just ask L<AnyEvent>
38     to choose any available event loop for him.
39    
40     Read more about this in the main documentation of the L<AnyEvent> module.
41    
42 elmex 1.2 =head2 Network programming and AnyEvent
43 elmex 1.1
44     However, AnyEvent is not just a simple abstraction anymore. It comes with
45     some very useful utility modules like L<AnyEvent::Handle>, L<AnyEvent::DNS>
46     and L<AnyEvent::Socket> that make your life as non-blocking network programmer
47     a lot easier.
48    
49     Now an introduction into these three submodules:
50    
51     =head3 L<AnyEvent::Handle>
52    
53     This module handles non-blocking IO on filehandles in a event based
54     manner. It provides a wrapper object around your filehandle that provides
55     queueing and buffering of incoming and outgoing data for you.
56    
57     More about this later.
58    
59     =head3 L<AnyEvent::Socket>
60    
61     This module provides you with functions that handle internet socket creation
62     and IP address magic. The two main functions are C<tcp_connect> and
63     C<tcp_server>. The former will connect a (streaming) socket to an internet host
64     for you and the later will make a server socket for you, to accept connections.
65    
66     This module also comes with transparent IPv6 support, this means: If you
67     write your programs with this module, you will be IPv6 ready.
68    
69     =head3 L<AnyEvent::DNS>
70    
71     This module allows fully asynchronous DNS resolution, and is used for example
72     by L<AnyEvent::Socket> to resolve hostnames and service ports.
73 elmex 1.2
74     =head2 First experiments with AnyEvent::Handle
75    
76     Now lets start with something simple, a program that reads non-blocking
77     from standard input:
78    
79     #!/opt/perl/bin/perl
80     use AnyEvent;
81     use AnyEvent::Handle;
82    
83     my $end_prog = AnyEvent->condvar;
84    
85     my $handle =
86     AnyEvent::Handle->new (
87     fh => \*STDIN,
88     on_eof => sub {
89     print "received EOF, exiting...\n";
90     $end_prog->broadcast;
91     },
92     on_error => sub {
93     print "error while reading from STDIN: $!\n";
94     $end_prog->broadcast;
95     }
96     );
97    
98     $handle->push_read (sub {
99     my ($handle) = @_;
100    
101     if ($handle->rbuf =~ s/^.*?\bend\b.*$//s) {
102     print "got 'end', existing...\n";
103     $end_prog->broadcast;
104     return 1
105     }
106    
107     0
108     });
109    
110     $end_prog->wait;
111    
112     Lets go through it step by step:
113    
114     #!/opt/perl/bin/perl
115     use AnyEvent;
116     use AnyEvent::Handle;
117    
118     Nothing new here, just load AnyEvent for the event loop and AnyEvent::Handle.
119    
120     my $end_prog = AnyEvent->condvar;
121    
122     Here a 'condition variable' is created. It represents the condition when the
123     program wants to terminate. We will later 'wait' for that condition, which
124     will choose and create an event loop for us.
125    
126     my $handle =
127     AnyEvent::Handle->new (
128     fh => \*STDIN,
129     on_eof => sub {
130     print "received EOF, exiting...\n";
131     $end_prog->broadcast;
132     },
133    
134     We create a handle which will read from the standard input filehandle.
135     Setting the C<on_eof> callback is required for every filehandle, as that is a
136     condition that we need to check always if we are working with filehandles,
137     to prevent reading or writing to a closed filehandle.
138    
139     on_error => sub {
140     print "error while reading from STDIN: $!\n";
141     $end_prog->broadcast;
142     }
143     );
144    
145     The C<on_error> callback is not required, but we set it here in case any
146     error happens when we read from the filehandle. It's usually a good idea to
147     set this callback also and at least print some diagnostics. Already in our
148     small example an error can happen. More to this later...
149    
150     $handle->push_read (sub {
151    
152     Here we push a general read callback on the read queue, that will wait until we
153     received all the data we wanted to receive. L<AnyEvent::Handle> has two queues
154     per filehandle, a read and a write queue. The write queue queues pending data
155     that waits to be written to the filehandle. And the read queue queues reading
156     callbacks. For more details see the documentation L<AnyEvent::Handle> about the
157     READ QUEUE and WRITE QUEUE.
158    
159     my ($handle) = @_;
160    
161     if ($handle->rbuf =~ s/^.*?\bend\b.*$//s) {
162     print "got 'end', existing...\n";
163     $end_prog->broadcast;
164     return 1
165     }
166    
167     0
168     });
169    
170     This code waits until the word 'end' has been seen in the data received
171     on standard input. Once we encounter the stop word 'end' we remove everything from
172     the read buffer and call the condition variable we setup earlier, that signals
173     our 'end of program' condition. And the callback returns with a true value,
174     that signals we are done with reading all the data we were interested in (all data until
175     the word 'end' has been seen).
176    
177     In all other cases, when the stop word has not been seen yet, we just return a false
178     value, to indicate that we are not finished yet.
179    
180     The C<rbuf> method returns our read buffer, that we can directly modify as lvalue.
181     Alternatively we also could have written:
182    
183     if ($handle->{rbuf} =~ s/^.*?\bend\b.*$//s) {
184    
185    
186     $end_prog->wait;
187    
188     This last line will wait blocking for the condition that our program wants to
189     exit. C<wait> will setup an event loop for us and wait for IO, timers or signals.
190    
191     The key points were:
192    
193     =over 4
194    
195     =item * Condition variables used to start an event loop.
196    
197     =item * Registering the basic callbacks on AnyEvent::Handles.
198    
199     =item * Processing data in the read buffer.
200    
201     =back