… | |
… | |
37 | program. And even there he doesn't have to choose, he can just ask L<AnyEvent> |
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. |
38 | to choose any available event loop for him. |
39 | |
39 | |
40 | Read more about this in the main documentation of the L<AnyEvent> module. |
40 | Read more about this in the main documentation of the L<AnyEvent> module. |
41 | |
41 | |
42 | =head2 Network programming |
42 | =head2 Network programming and AnyEvent |
43 | |
43 | |
44 | However, AnyEvent is not just a simple abstraction anymore. It comes with |
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> |
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 |
46 | and L<AnyEvent::Socket> that make your life as non-blocking network programmer |
47 | a lot easier. |
47 | a lot easier. |
… | |
… | |
68 | |
68 | |
69 | =head3 L<AnyEvent::DNS> |
69 | =head3 L<AnyEvent::DNS> |
70 | |
70 | |
71 | This module allows fully asynchronous DNS resolution, and is used for example |
71 | This module allows fully asynchronous DNS resolution, and is used for example |
72 | by L<AnyEvent::Socket> to resolve hostnames and service ports. |
72 | by L<AnyEvent::Socket> to resolve hostnames and service ports. |
|
|
73 | |
|
|
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 |