… | |
… | |
26 | |
26 | |
27 | Each I<node> is distinguished from other I<nodes> running on the same host or |
27 | Each I<node> is distinguished from other I<nodes> running on the same host or |
28 | multiple hosts in a network by it's I<node ID>. A I<node ID> can be manually |
28 | multiple hosts in a network by it's I<node ID>. A I<node ID> can be manually |
29 | assigned or L<AnyEvent::MP> will assign one it self for you. |
29 | assigned or L<AnyEvent::MP> will assign one it self for you. |
30 | |
30 | |
31 | So, you might want to visualize it like this (setup is two nodes: Node C<A> (in |
31 | So, you might want to visualize it like this (setup is two nodes (more are of |
32 | UNIX process 7066) with ports C<ABC> and C<DEF> and C<B> (in UNIX process 8321) |
32 | course possible): Node C<A> (in UNIX process 7066) with ports C<ABC> and C<DEF> |
33 | with ports C<FOO> and C<BAR>). |
33 | and C<B> (in UNIX process 8321) with ports C<FOO> and C<BAR>). |
34 | |
34 | |
35 | |
35 | |
36 | |- PID: 7066 -| |- PID: 8321 -| |
36 | |- PID: 7066 -| |- PID: 8321 -| |
37 | | | | | |
37 | | | | | |
38 | | Node ID: A | | Node ID: B | |
38 | | Node ID: A | | Node ID: B | |
… | |
… | |
44 | |-------------| |-------------| |
44 | |-------------| |-------------| |
45 | |
45 | |
46 | The strings for the ports here are just for illustrative purposes. Even if in |
46 | The strings for the ports here are just for illustrative purposes. Even if in |
47 | reality I<ports> in L<AnyEvent::MP> are also identified by strings they can't |
47 | reality I<ports> in L<AnyEvent::MP> are also identified by strings they can't |
48 | be choosen manually and are assigned randomly. These I<port ids> should also |
48 | be choosen manually and are assigned randomly. These I<port ids> should also |
49 | not be used directly for other purposes than refering to an endpoint for |
49 | not be used directly for other purposes than referring to an endpoint for |
50 | messages. |
50 | messages. |
51 | |
51 | |
52 | The next sections will explain the API of L<AnyEvent::MP>. First the API is |
52 | The next sections will explain the API of L<AnyEvent::MP>. First the API is |
53 | layed out by simple examples. Later some more complex idioms are introduced, |
53 | laid out by simple examples. Later some more complex idioms are introduced, |
54 | which are maybe useful to solve some realworld purposes. |
54 | which are maybe useful to solve some real world purposes. |
55 | |
55 | |
56 | # In this tutorial I'll show you how to write a simple chat server based on |
56 | # In this tutorial I'll show you how to write a simple chat server based on |
57 | # L<AnyEvent::MP>. This example is used because it nicely shows how to organise a |
57 | # L<AnyEvent::MP>. This example is used because it nicely shows how to organise a |
58 | # simple application, but keep in mind that every node trusts any other, so this |
58 | # simple application, but keep in mind that every node trusts any other, so this |
59 | # chat cannot be used to implement a real public chat server and client system, |
59 | # chat cannot be used to implement a real public chat server and client system, |
… | |
… | |
146 | |
146 | |
147 | B<If something does not work as expected, and for example tcpdump shows |
147 | B<If something does not work as expected, and for example tcpdump shows |
148 | that the connections are closed almost immediately, you should make sure |
148 | that the connections are closed almost immediately, you should make sure |
149 | that F<~/.perl-anyevent-mp> is the same on all hosts/user accounts that |
149 | that F<~/.perl-anyevent-mp> is the same on all hosts/user accounts that |
150 | you try to connect with each other!> |
150 | you try to connect with each other!> |
|
|
151 | |
|
|
152 | Thats all for now, there is more fiddling around with the C<aemp> utility |
|
|
153 | later. |
|
|
154 | |
|
|
155 | =head1 Passing Messages Between Processes |
|
|
156 | |
|
|
157 | =head2 The Receiver |
|
|
158 | |
|
|
159 | Lets split the previous example up into two small programs. First the |
|
|
160 | receiver application: |
|
|
161 | |
|
|
162 | #!/opt/perl/bin/perl |
|
|
163 | use AnyEvent; |
|
|
164 | use AnyEvent::MP; |
|
|
165 | use AnyEvent::MP::Global; |
|
|
166 | |
|
|
167 | initialise_node "eg_simple_receiver"; |
|
|
168 | |
|
|
169 | my $port = port; |
|
|
170 | |
|
|
171 | AnyEvent::MP::Global::register $port, "eg_receivers"; |
|
|
172 | |
|
|
173 | rcv $port, test => sub { |
|
|
174 | my ($data, $reply_port) = @_; |
|
|
175 | |
|
|
176 | print "Received data: " . $data . "\n"; |
|
|
177 | }; |
|
|
178 | |
|
|
179 | AnyEvent->condvar->recv; |
|
|
180 | |
|
|
181 | =head3 AnyEvent::MP::Global |
|
|
182 | |
|
|
183 | Now, that wasn't too bad, was it? Ok, lets step through the new functions |
|
|
184 | and modules that have been used. For starters there is now an additional |
|
|
185 | module loaded: L<AnyEvent::MP::Global>. |
|
|
186 | |
|
|
187 | That module provides us with a I<global registry>, which lets us share data |
|
|
188 | among all I<nodes> in a network. Why do we need it you might ask? |
|
|
189 | |
|
|
190 | The I<port ids> are just random strings, assigned by L<AnyEvent::MP>. We can't |
|
|
191 | know those I<port ids> in advance, so we don't know which I<port id> to send |
|
|
192 | messages to if the message is to be passed between I<nodes> (or UNIX |
|
|
193 | processes). To find the right I<port> of another I<node> in the network we will |
|
|
194 | need to communicate that somehow to the sender. And exactly that is what |
|
|
195 | L<AnyEvent::MP::Global> provides. |
|
|
196 | |
|
|
197 | =head3 initialise_node And The Network |
|
|
198 | |
|
|
199 | Now, lets have a look at the next new thing, the C<initialise_node>: |
|
|
200 | |
|
|
201 | initialise_node "eg_simple_receiver"; |
|
|
202 | |
|
|
203 | Before we are able to send messages to other nodes we have to initialise |
|
|
204 | ourself. The first argument, the string C<"eg_simple_receiver">, is called the |
|
|
205 | I<profile> of this node. A profile holds some information about the application |
|
|
206 | that is going to be a node in an L<AnyEvent::MP> network. |
|
|
207 | |
|
|
208 | Most importantly the profile allows you to set the I<node id> that your |
|
|
209 | application will use. You can also set I<binds> in the profile, meaning that |
|
|
210 | you can define TCP ports that the application will listen on for incoming |
|
|
211 | connections from other nodes of the network. |
|
|
212 | |
|
|
213 | Next you can configure I<seeds> in profile. A I<seed> is just a TCP endpoint |
|
|
214 | which tells the application where to find other nodes of it's network. To |
|
|
215 | explain this a bit more detailed we have to look at the topology of an |
|
|
216 | L<AnyEvent::MP> network. The topology is called a I<fully connected mesh>, here |
|
|
217 | an example with 4 nodes: |
|
|
218 | |
|
|
219 | N1--N2 |
|
|
220 | | \/ | |
|
|
221 | | /\ | |
|
|
222 | N3--N4 |
|
|
223 | |
|
|
224 | Now imagine another I<node> C<N5>. wants to connect itself to that network: |
|
|
225 | |
|
|
226 | N1--N2 |
|
|
227 | | \/ | N5 |
|
|
228 | | /\ | |
|
|
229 | N3--N4 |
|
|
230 | |
|
|
231 | The new node needs to know the I<binds> of all of those 4 already connected |
|
|
232 | nodes. And exactly this is what the I<seeds> are for. Now lets assume that |
|
|
233 | the new node C<N5> has as I<seed> the TCP endpoint of the node C<N2>. |
|
|
234 | It then connects to C<N2>: |
|
|
235 | |
|
|
236 | N1--N2____ |
|
|
237 | | \/ | N5 |
|
|
238 | | /\ | |
|
|
239 | N3--N4 |
|
|
240 | |
|
|
241 | C<N2> then tells C<N5> the I<binds> of the other nodes it is connected to, |
|
|
242 | and C<N5> builds up the rest of the connections: |
|
|
243 | |
|
|
244 | /--------\ |
|
|
245 | N1--N2____| |
|
|
246 | | \/ | N5 |
|
|
247 | | /\ | /| |
|
|
248 | N3--N4--- | |
|
|
249 | \________/ |
|
|
250 | |
|
|
251 | Finished. C<N5> is now happily connected to the rest of the network. |
151 | |
252 | |
152 | =head1 The Chat Client |
253 | =head1 The Chat Client |
153 | |
254 | |
154 | OK, lets start by implementing the "frontend" of the client. We will |
255 | OK, lets start by implementing the "frontend" of the client. We will |
155 | develop the client first and postpone the server for later, as the most |
256 | develop the client first and postpone the server for later, as the most |