ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/MP/Intro.pod
(Generate patch)

Comparing AnyEvent-MP/MP/Intro.pod (file contents):
Revision 1.3 by elmex, Mon Aug 3 08:40:29 2009 UTC vs.
Revision 1.4 by root, Mon Aug 3 09:19:21 2009 UTC

1=head1 Message Passing for the non-blocked Mind 1=head1 Message Passing for the Non-Blocked Mind
2 2
3=head2 Introduction and Terminology 3=head2 Introduction and Terminology
4 4
5This is a Tutorial about how to get the swing of the new L<AnyEvent::MP> 5This is a tutorial about how to get the swing of the new L<AnyEvent::MP>
6module. Which allows us to transparently pass messages to our own process and 6module. Which allows us to transparently pass messages to our own process and
7to other process on other or the same host. 7to other process on other or the same host.
8 8
9What kind of messages? Well, basically a message here means a list of Perl 9What kind of messages? Well, basically a message here means a list of
10strings, numbers, hashes and arrays, mostly everything that can be expressed as 10Perl strings, numbers, hashes and arrays, mostly everything that can be
11L<JSON> string. 11expressed in a L<JSON> text (as JSON is used by default in the protocol).
12 12
13And next you might ask: between which entities are those messages "passed"? 13And next you might ask: between which entities are those messages being "passed"?
14Basically between C<nodes>, which are basically your applications (as in 14Basically between C<nodes>, which are basically your applications (as in
15processes) that use L<AnyEvent::MP> that run either on the same or different 15processes) that use L<AnyEvent::MP> that run either on the same or different
16hosts. 16hosts.
17 17
18In this Tutorial I'll show you how to write a simple chat server based on 18In this tutorial I'll show you how to write a simple chat server based on
19L<AnyEvent::MP>. 19L<AnyEvent::MP>.
20 20
21=head2 The Chat Client 21=head2 The Chat Client
22 22
23Ok, lets start by implementing the "frontend" of the client. We will delay the 23OK, lets start by implementing the "frontend" of the client. We will delay the
24explanation and the code of the server until we finished the client, as the 24explanation and the code of the server until we finished the client, as the
25most complex things actually happen in the client. 25most complex things actually happen in the client.
26 26
27We will use L<AnyEvent::Handle> to do non-blocking IO read on standard input: 27We will use L<AnyEvent::Handle> to do non-blocking IO read on standard input:
28 28
57 } 57 }
58 ); 58 );
59 59
60 $quit_cv->recv; 60 $quit_cv->recv;
61 61
62This is now a very basic client. Explaining explicitly what L<AnyEvent::Handle> 62This is now a very basic client. Explaining explicitly what
63does or what a I<condvar> is all about is out of scope of this document, please 63L<AnyEvent::Handle> does or what a I<condvar> is all about is out of scope
64consult L<AnyEvent::Intro> or the manpages for L<AnyEvent> and 64of this document, please consult L<AnyEvent::Intro> or the manual pages
65L<AnyEvent::Handle>. 65for L<AnyEvent> and L<AnyEvent::Handle>.
66 66
67=head2 First Step Into Messaging 67=head2 First Step Into Messaging
68 68
69Now we take a look at L<AnyEvent::MP>. We need to know what to do in 69Now we take a look at L<AnyEvent::MP>. We need to know what to do in
70C<send_message>. This is an example how it might look like: 70C<send_message>. This is an example of how it might look like:
71 71
72 ... # the use lines from the above snippet 72 ... # the use lines from the above snippet
73 73
74 use AnyEvent::MP; 74 use AnyEvent::MP;
75 75
83 83
84The C<snd> function is exported by L<AnyEvent::MP>, it stands for 'send a 84The C<snd> function is exported by L<AnyEvent::MP>, it stands for 'send a
85message'. The first argument is the I<port> (a I<port> is something that can 85message'. The first argument is the I<port> (a I<port> is something that can
86receive messages) of the server which will receive the message . How we get it 86receive messages) of the server which will receive the message . How we get it
87will be explained in the next step. The next arguments of C<snd> are 87will be explained in the next step. The next arguments of C<snd> are
88C<'message'> and C<$msg> are the first two elements of the I<message> (a 88C<message> and C<$msg> are the first two elements of the I<message> (a
89I<message> in L<AnyEvent::MP> is a be a simple list of values, which can be 89I<message> in L<AnyEvent::MP> is a be a simple list of values, which can be
90sent to I<ports>). 90sent to I<ports>).
91 91
92Thats all fine so far, but how do we get the C<$server_port>? Well, we will 92Thats all fine so far, but how do we get the C<$server_port>? Well, we will
93need to get the unique I<port id> of the server's port where he wants to 93need to get the unique I<port id> of the server's port where he wants to
94receive all the incoming chat messages. A I<port id> is unfortunately a very 94receive all the incoming chat messages. A I<port id> is unfortunately a very
95unique string, which we are unable to know in advance. But L<AnyEvent::MP> 95unique string, which we are unable to know in advance. But L<AnyEvent::MP>
96supports the concept of 'well known ports', which is basically a port on the 96supports the concept of 'well known ports', which is basically a port on the
97server side registered under a well known name. For example, the server has a 97server side registered under a well known name. For example, the server has a
98port for receiving chat messages with a unique I<port id> and registered it 98port for receiving chat messages with a unique I<port id> and registered it
99under the name C<"chatter">. 99under the name C<chatter>.
100
101BTW, these "well known port names" should follow similar rules as Perl
102identifiers, so you should prefix them with your package/module name to
103make them unique, unless you use them in the main program.
100 104
101As I<messages> can only be sent to a I<port id> and not just to a name we have 105As I<messages> can only be sent to a I<port id> and not just to a name we have
102to ask the server I<node> what I<port id> has the well known port with the 106to ask the server I<node> what I<port id> has the well known port with the
103name C<"chatter"> 107name C<chatter>.
104 108
105Another new term, what is a I<node>: The messaging network that can be created with 109Another new term, what is a I<node>: The messaging network that can be created with
106L<AnyEvent::MP> consists of I<nodes>. A I<node> handles all the connection and 110L<AnyEvent::MP> consists of I<nodes>. A I<node> handles all the connection and
107low level message sending logic for it's application. The application in this 111low level message sending logic for its application. The application in this
108case is the server. Also every client has/is a I<node>. 112case is the server. Also every client has/is a I<node>.
109 113
110=head2 Getting The Chatter Port 114=head2 Getting The Chatter Port
111 115
112Ok, lots of talk, now some code. Now we will actually get the C<$server_port> 116Ok, lots of talk, now some code. Now we will actually get the C<$server_port>
161 165
162Next thing is the C<$server_node>. In order to refer to another node we need 166Next thing is the C<$server_node>. In order to refer to another node we need
163some kind of string to reference it. The I<noderef> is basically a comma 167some kind of string to reference it. The I<noderef> is basically a comma
164seperated list of C<host:port> pairs. We assume in this tutorial that the 168seperated list of C<host:port> pairs. We assume in this tutorial that the
165server runs on your localhost at port 1299, this gives us the noderef 169server runs on your localhost at port 1299, this gives us the noderef
166C<"localhost:1299">. 170C<localhost:1299>.
167 171
168Now you might ask what the C<"#"> at the end in C<$server_node> the above 172Now you might ask what the C<#> at the end in C<$server_node> the above
169example is about. Well, what I didn't tell you yet is that each I<node> has a 173example is about. Well, what I didn't tell you yet is that each I<node> has a
170default I<port> to receive messages. The default port is the empty string 174default I<port> to receive messages. The default port is the empty string
171C<"">. The I<default port> of a I<node> also provides some special services for 175C<"">. The I<default port> of a I<node> also provides some special services for
172us, for example resolving a well known port to a I<port id>. 176us, for example resolving a well known port to a I<port id>.
173 177
174Now to this line: 178Now to this line:
175 179
176 snd $server_node, wkp => "chatter", "$client_port", "resolved"; 180 snd $server_node, wkp => "chatter", "$client_port", "resolved";
177 181
178We send a message with first element being C<'wkp'> (standing for 'well known 182We send a message with first element being C<wkp> (standing for 'well known
179port'). Then the well known port name that we want to resolve to a I<port id>: 183port'). Then the well known port name that we want to resolve to a I<port id>:
180C<"chatter">. And in order for the server node to be able to send us back the 184C<chatter>. And in order for the server node to be able to send us back the
181resolved I<port id> we have to tell it where to send the result message: The 185resolved I<port id> we have to tell it where to send the result message: The
182result message will have as it's first argument the string C<"resolved"> and 186result message will have as it's first argument the string C<resolved> and
183will be sent to C<"$client_port"> (the I<port id> of our own just created 187will be sent to C<$client_port> (the I<port id> of our own just created
184port). 188port).
185 189
186Next this is this: 190Next comes the receiver for this C<wkp> request.
187 191
188 $client_port->rcv (resolved => sub { 192 $client_port->rcv (resolved => sub {
189 my ($client_port, $type, $chatter_port_id) = @_; 193 my ($client_port, $type, $chatter_port_id) = @_;
190 ... 194 ...
191 1 195 1
192 }); 196 });
193 197
194This sets up a receiver on our own port for the result message with the first 198This sets up a receiver on our own port for the result message with the first
195argument being the string C<"resolved">. Receivers can match the contents of 199argument being the string C<resolved>. Receivers can match the contents of
196the messages before actually 'sending' it to the given callback. 200the messages before actually 'sending' it to the given callback.
197 201
198B<Please note> that the given callback has to return either a true or a false 202B<Please note> that the given callback has to return either a true or a false
199value for indicating whether it is B<done> (true value) or still wants to 203value for indicating whether it is B<done> (true value) or still wants to
200B<continue> (false value) receiving messages. 204B<continue> (false value) receiving messages.
201 205
202In this case we tell the C<$client_port> to look into the received messages and 206In this case we tell the C<$client_port> to look into the received messages and
203look for the string C<"resolved"> in the first element of the message. If it is 207look for the string C<resolved> in the first element of the message. If it is
204found, the given callback will be called with the C<$client_port> as first 208found, the given callback will be called with the C<$client_port> as first
205argument, and the message as the remaining arguments. 209argument, and the message as the remaining arguments.
206 210
207We name the first element of the message C<$type> in this case. It's a common 211We name the first element of the message C<$type> in this case. It's a common
208idiom to code the 'type' of a message into it's first element, this allows for 212idiom to code the 'type' of a message into it's first element, this allows for
209simple matching. 213simple matching.
210 214
211The result message will contain the I<port id> of the well known port C<"chatter"> 215The result message will contain the I<port id> of the well known port C<chatter>
212as next element, and will be put in C<$chatter_port_id>. 216as next element, and will be put in C<$chatter_port_id>.
213 217
214Next we just assign C<$server_port> and return a 1 (a true value) 218Next we just assign C<$server_port> and return a 1 (a true value)
215from the callback. It indicates that we are done and don't want to receive 219from the callback. It indicates that we are done and don't want to receive
216further C<'resolved'> messages with this callback. 220further C<resolved> messages with this callback.
217 221
218Now we continue to the rest of the client by calling C<send> on 222Now we continue to the rest of the client by calling C<send> on
219C<$resolved_cv>. 223C<$resolved_cv>.
220 224
221First new step after this is setting up the chat message receiver callback. 225First new step after this is setting up the chat message receiver callback.
225 229
226 print "chat> $msg\n"; 230 print "chat> $msg\n";
227 0 231 0
228 }); 232 });
229 233
230We assume that all messages that are broadcasted to all clients by the server 234We assume that all messages that are broadcast to all clients by the server
231will contain as first element the string C<"message"> and the actual message as 235will contain the string C<message> as first element, and the actual message as
232second element. The callback returns a false value this time, to indicate that 236second element. The callback returns a false value this time, to indicate that
233it wants to continue receiving messages. 237it wants to continue receiving messages.
234 238
235Last but not least we actually tell the server to send us 239Last but not least we actually tell the server to send us
236the new chat messages from other clients. We do so by sending the 240the new chat messages from other clients. We do so by sending the
237message type C<'join'> followed by our own I<port id>. 241message type C<join> followed by our own I<port id>.
238 242
239 # send the server a 'join' message: 243 # send the server a 'join' message:
240 snd $server_port, join => "$client_port"; 244 snd $server_port, join => "$client_port";
241 245
242Then the server knows where to send all the new messages to. 246Then the server knows where to send all the new messages to.
244=head2 The Finished Client 248=head2 The Finished Client
245 249
246This is the complete client script: 250This is the complete client script:
247 251
248 #!perl 252 #!perl
253
249 use AnyEvent; 254 use AnyEvent;
250 use AnyEvent::Handle; 255 use AnyEvent::Handle;
251 use AnyEvent::MP; 256 use AnyEvent::MP;
252 257
253 my $resolved_cv = AnyEvent->condvar; 258 my $resolved_cv = AnyEvent->condvar;
316 $quit_cv->recv; 321 $quit_cv->recv;
317 322
318=head2 The Server 323=head2 The Server
319 324
320Ok, now finally to the server. What do we need? Well, we need to setup 325Ok, now finally to the server. What do we need? Well, we need to setup
321the well known port C<"chatter"> where all clients send their messages to. 326the well known port C<chatter> where all clients send their messages to.
322 327
323Up and into code right now: 328Up and into code right now:
324 329
325 #!perl 330 #!perl
331
326 use AnyEvent; 332 use AnyEvent;
327 use AnyEvent::MP; 333 use AnyEvent::MP;
328 334
329 become_public "localhost:1299"; 335 become_public "localhost:1299";
330 336
390L<AnyEvent::MP> 396L<AnyEvent::MP>
391 397
392=head1 AUTHOR 398=head1 AUTHOR
393 399
394 Robin Redeker <elmex@ta-sa.org> 400 Robin Redeker <elmex@ta-sa.org>
401

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines