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.7 by elmex, Tue Aug 4 07:58:53 2009 UTC vs.
Revision 1.8 by root, Tue Aug 4 20:00:00 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=head1 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
7to other process on other or the same host. 7and to other processes on another or the same host.
8 8
9What kind of messages? Well, basically a message here means a list of 9What kind of messages? Well, basically a message here means a list of
10Perl strings, numbers, hashes and arrays, mostly everything that can be 10Perl strings, numbers, hashes and arrays, mostly everything that can be
11expressed in a L<JSON> text (as JSON is used by default in the protocol). 11expressed as 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 being "passed"? 13And next you might ask: between which entities are those messages
14Basically between C<nodes>, which are basically your applications (as in 14being "passed"? Basically between C<nodes>: a nodes is basically a
15processes) that use L<AnyEvent::MP> that run either on the same or different 15process/program that use L<AnyEvent::MP> and can run either on the same or
16hosts. 16different hosts.
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 System Requirements 21=head1 System Requirements
22 22
23Before we can start we have to make sure some things work on your 23Before we can start we have to make sure some things work on your
24system. First of all the host C<localhost> should resolve to a local 24system.
25IP address. Next you should be able to do TCP over that address.
26 25
27You should of course also make sure that L<AnyEvent> and L<AnyEvent::MP> 26You should of course also make sure that L<AnyEvent> and L<AnyEvent::MP>
28are installed. But how to do that is out of scope of this tutorial. 27are installed. But how to do that is out of scope of this tutorial.
29 28
30Then we have to setup a I<shared secret>. For two L<AnyEvent::MP> nodes 29Then we have to setup a I<shared secret>. For two L<AnyEvent::MP> nodes to
31to be able to communicate with each other and authenticate each other 30be able to communicate with each other and authenticate each other it is
32it is necessary to setup a I<shared secret>. For testing you can write a 31necessary to setup the same I<shared secret> for both of them. For testing
33random string followed by a newline into the file C<.aemp-secret> in your 32you can write a random string into the file C<.aemp-secret> in your home
34home directory: 33directory:
35 34
35 mcookie > ~/.aemp-secret
36
37 # or something more predictable
36 echo "secret123#4blabla_please_pick_your_own" > ~/.aemp-secret 38 echo "secret123#4blabla_please_pick_your_own" > ~/.aemp-secret
37 39
38Only if the nodes that want to connect to each other have the same I<shared 40Connections will only be successful when the nodes that want to connect
39secret> connections will be successful. 41to each other have the same I<shared secret>. For more security, you can
42put a self-signed SSL/TLS key/certificate pair into the file (or a normal
43key/certificate and it's CA certificate).
40 44
41B<If something does not work as expected, and for example tcpdump shows 45B<If something does not work as expected, and for example tcpdump shows
42that the connections are broken up early, you should make sure that ~/.aemp-secret 46that the connections are closed almost immediatly, you should make sure
43is the same on both hosts/user accounts you are connecting!> 47that F<~/.aemp-secret> is the same on all hosts/user accounts that you try
48to connect with each other!>
44 49
45=head2 The Chat Client 50=head1 The Chat Client
46 51
47OK, lets start by implementing the "frontend" of the client. We will delay the 52OK, lets start by implementing the "frontend" of the client. We will
48explanation and the code of the server until we finished the client, as the 53develop the client first and postpone the server for later, as the most
49most complex things actually happen in the client. 54complex things actually happen in the client.
50 55
51We will use L<AnyEvent::Handle> to do non-blocking IO read on standard input: 56We will use L<AnyEvent::Handle> to do non-blocking IO read on standard
57input (all of this code deals with actually handling user input, no
58message passing yet):
52 59
53 #!perl 60 #!perl
61
54 use AnyEvent; 62 use AnyEvent;
55 use AnyEvent::Handle; 63 use AnyEvent::Handle;
56 64
57 sub send_message { 65 sub send_message {
58 die "This is where we will send the messages to the server" 66 die "This is where we will send the messages to the server"
62 # make an AnyEvent condition variable for the 'quit' condition 70 # make an AnyEvent condition variable for the 'quit' condition
63 # (when we want to exit the client). 71 # (when we want to exit the client).
64 my $quit_cv = AnyEvent->condvar; 72 my $quit_cv = AnyEvent->condvar;
65 73
66 my $stdin_hdl = AnyEvent::Handle->new ( 74 my $stdin_hdl = AnyEvent::Handle->new (
67 fh => \*STDIN, 75 fh => *STDIN,
76 on_error => sub { $quit_cv->send },
68 on_read => sub { 77 on_read => sub {
69 my ($hdl) = @_; 78 my ($hdl) = @_;
70 79
71 $hdl->push_read (line => sub { 80 $hdl->push_read (line => sub {
72 my ($hdl, $line) = @_; 81 my ($hdl, $line) = @_;
73 82
74 if ($line =~ /^\/quit/) { # /quit will end the client 83 if ($line =~ /^\/quit/) { # /quit will end the client
75 $quit_cv->send; 84 $quit_cv->send;
76
77 } else { 85 } else {
78 send_message ($line); 86 send_message ($line);
79 } 87 }
80 }); 88 });
81 } 89 }
86This is now a very basic client. Explaining explicitly what 94This is now a very basic client. Explaining explicitly what
87L<AnyEvent::Handle> does or what a I<condvar> is all about is out of scope 95L<AnyEvent::Handle> does or what a I<condvar> is all about is out of scope
88of this document, please consult L<AnyEvent::Intro> or the manual pages 96of this document, please consult L<AnyEvent::Intro> or the manual pages
89for L<AnyEvent> and L<AnyEvent::Handle>. 97for L<AnyEvent> and L<AnyEvent::Handle>.
90 98
91=head2 First Step Into Messaging 99=head1 First Step Into Messaging
92 100
93Now we take a look at L<AnyEvent::MP>. We need to know what to do in 101To supply the C<send_message> function we now take a look at
94C<send_message>. This is an example of how it might look like: 102L<AnyEvent::MP>. This is an example of how it might look like:
95 103
96 ... # the use lines from the above snippet 104 ... # the use lines from the above snippet
97 105
98 use AnyEvent::MP; 106 use AnyEvent::MP;
99 107
103 snd $server_port, message => $msg; 111 snd $server_port, message => $msg;
104 } 112 }
105 113
106 ... # the rest of the above script 114 ... # the rest of the above script
107 115
108The C<snd> function is exported by L<AnyEvent::MP>, it stands for 'send a 116The C<snd> function is exported by L<AnyEvent::MP>, it stands for 'send
109message'. The first argument is the I<port> (a I<port> is something that can 117a message'. The first argument is the I<port> (a I<port> is something
110receive messages) of the server which will receive the message . How we get it 118that can receive messages, represented by a printable string) of the
111will be explained in the next step. The next arguments of C<snd> are 119server which will receive the message. How we get this port will be
112C<message> and C<$msg> are the first two elements of the I<message> (a 120explained in the next step.
113I<message> in L<AnyEvent::MP> is a be a simple list of values, which can be
114sent to I<ports>).
115 121
116Thats all fine so far, but how do we get the C<$server_port>? Well, we will 122The remaining arguments of C<snd> are C<message> and C<$msg>, the first
117need to get the unique I<port id> of the server's port where he wants to 123two elements of the I<message> (a I<message> in L<AnyEvent::MP> is a
118receive all the incoming chat messages. A I<port id> is unfortunately a very 124simple list of values, which can be sent to a I<port>).
119unique string, which we are unable to know in advance. But L<AnyEvent::MP> 125
120supports the concept of 'well known ports', which is basically a port on the 126So all the function does is send the two values C<message> (a constant
121server side registered under a well known name. For example, the server has a 127string to tell the server what to expect) and the actual message string.
128
129Thats all fine and simple so far, but where do we get the
130C<$server_port>? Well, we need to get the unique I<port id> of the
131server's port where it wants to receive all the incoming chat messages. A
132I<port id> is unfortunately a very unique string, which we are unable
133to know in advance. But L<AnyEvent::MP> supports the concept of 'well
134known ports', which is basically a port on the server side registered
135under a well known name. For example, the server has a port for receiving
122port for receiving chat messages with a unique I<port id> and registered it 136chat messages with a unique I<port id> and registered it under the name
123under the name C<chatter>. 137C<chatter>.
124 138
125BTW, these "well known port names" should follow similar rules as Perl 139BTW, these "well known port names" should follow similar rules as Perl
126identifiers, so you should prefix them with your package/module name to 140identifiers, so you should prefix them with your package/module name to
127make them unique, unless you use them in the main program. 141make them unique, unless you use them in the main program.
128 142
133Another new term, what is a I<node>: The messaging network that can be created with 147Another new term, what is a I<node>: The messaging network that can be created with
134L<AnyEvent::MP> consists of I<nodes>. A I<node> handles all the connection and 148L<AnyEvent::MP> consists of I<nodes>. A I<node> handles all the connection and
135low level message sending logic for its application. The application in this 149low level message sending logic for its application. The application in this
136case is the server. Also every client has/is a I<node>. 150case is the server. Also every client has/is a I<node>.
137 151
138=head2 Getting The Chatter Port 152=head1 Getting The Chatter Port
139 153
140Ok, lots of talk, now some code. Now we will actually get the C<$server_port> 154Ok, lots of talk, now some code. Now we will actually get the C<$server_port>
141from the backend: 155from the backend:
142 156
143 ... 157 ...
267 # send the server a 'join' message: 281 # send the server a 'join' message:
268 snd $server_port, join => "$client_port"; 282 snd $server_port, join => "$client_port";
269 283
270Then the server knows where to send all the new messages to. 284Then the server knows where to send all the new messages to.
271 285
272=head2 The Completed Client 286=head1 The Completed Client
273 287
274This is the complete client script: 288This is the complete client script:
275 289
276 #!perl 290 #!perl
277 291
342 } 356 }
343 ); 357 );
344 358
345 $quit_cv->recv; 359 $quit_cv->recv;
346 360
347=head2 The Server 361=head1 The Server
348 362
349Ok, now finally to the server. What do we need? Well, we need to setup 363Ok, now finally to the server. What do we need? Well, we need to setup
350the well known port C<chatter> where all clients send their messages to. 364the well known port C<chatter> where all clients send their messages to.
351 365
352Up and into code right now: 366Up and into code right now:
402C<%client_ports> hash. In the receiver for the message type C<message> we will 416C<%client_ports> hash. In the receiver for the message type C<message> we will
403just iterate through all known C<%client_ports> and relay the message to them. 417just iterate through all known C<%client_ports> and relay the message to them.
404 418
405And thats it. 419And thats it.
406 420
407=head2 The Remaining Problems 421=head1 The Remaining Problems
408 422
409The shown implementation still has some bugs. For instance: How does the 423The shown implementation still has some bugs. For instance: How does the
410server know that the client isn't there anymore, and can cleanup the 424server know that the client isn't there anymore, and can cleanup the
411C<%client_ports> hash? And also the chat messages have no originator, 425C<%client_ports> hash? And also the chat messages have no originator,
412so we don't know who actually sent the message (which would be quite useful 426so we don't know who actually sent the message (which would be quite useful
416L<AnyEvent::MP> and explained some common idioms. 430L<AnyEvent::MP> and explained some common idioms.
417 431
418How to solve the reliability and C<%client_ports> cleanup problem will 432How to solve the reliability and C<%client_ports> cleanup problem will
419be explained later in this tutorial (TODO). 433be explained later in this tutorial (TODO).
420 434
421=head2 Inside The Protocol 435=head1 Inside The Protocol
422 436
423Now, for the interested parties, let me explain some details about the protocol 437Now, for the interested parties, let me explain some details about the protocol
424that L<AnyEvent::MP> nodes use to communicate to each other. If you are not 438that L<AnyEvent::MP> nodes use to communicate to each other. If you are not
425interested you can skip this section. 439interested you can skip this section.
426 440

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines