ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/MP/Intro.pod
Revision: 1.19
Committed: Fri Aug 28 15:24:16 2009 UTC (14 years, 9 months ago) by elmex
Branch: MAIN
Changes since 1.18: +53 -0 lines
Log Message:
receiver example done.

File Contents

# Content
1 =head1 Message Passing for the Non-Blocked Mind
2
3 =head1 Introduction and Terminology
4
5 This is a tutorial about how to get the swing of the new L<AnyEvent::MP>
6 module, which allows us to transparently pass messages to our own process
7 and to other processes on another or the same host.
8
9 What kind of messages? Well, basically a message here means a list of Perl
10 strings, numbers, hashes and arrays, anything that can be expressed as a
11 L<JSON> text (as JSON is used by default in the protocol).
12
13 It's custom in L<AnyEvent::MP> to have a string which describes the type of the
14 message as first element (this is called a I<tag> in L<AnyEvent::MP>), as some
15 API functions (C<rcv>) support matching it directly. So supposedly you want to
16 send a ping message with your current time to something, this is how such a
17 message might look like (in Perl syntax):
18
19 ['ping', 1251381636]
20
21 And next you might ask: between which entities are those messages being
22 I<passed>? They are I<passed> between I<ports>. I<ports> are just sources and
23 destinations for messages. How do these ports relate to things you know? Well,
24 each I<port> belongs to a I<node>, and a I<node> is just the UNIX process that
25 runs your L<AnyEvent::MP> application.
26
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
29 assigned or L<AnyEvent::MP> will assign one it self for you.
30
31 So, you might want to visualize it like this (setup is two nodes (more are of
32 course possible): Node C<A> (in UNIX process 7066) with ports C<ABC> and C<DEF>
33 and C<B> (in UNIX process 8321) with ports C<FOO> and C<BAR>).
34
35
36 |- PID: 7066 -| |- PID: 8321 -|
37 | | | |
38 | Node ID: A | | Node ID: B |
39 | | | |
40 | Port ABC =|= <----\ /-----> =|= Port FOO |
41 | | X | |
42 | Port DEF =|= <----/ \-----> =|= Port BAR |
43 | | | |
44 |-------------| |-------------|
45
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
48 be choosen manually and are assigned randomly. These I<port ids> should also
49 not be used directly for other purposes than referring to an endpoint for
50 messages.
51
52 The next sections will explain the API of L<AnyEvent::MP>. First the API is
53 laid out by simple examples. Later some more complex idioms are introduced,
54 which are maybe useful to solve some real world purposes.
55
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
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,
60 # but it can be used to implement a distributed chat server for example.
61
62 =head1 Passing Your First Message
63
64 As start lets have a look at the messaging API. The next example is just a
65 demo to show the basic elements of message passing with L<AnyEvent::MP>.
66 It shout just print: "Ending with: 123". So here the code:
67
68 use AnyEvent;
69 use AnyEvent::MP;
70
71 my $end_cv = AnyEvent->condvar;
72
73 my $port = port;
74
75 rcv $port, test => sub {
76 my ($data) = @_;
77 $end_cv->send ($data);
78 };
79
80 snd $port, test => 123;
81
82 print "Ending with: " . $end_cv->recv . "\n";
83
84 It already contains most functions of the essential L<AnyEvent::MP> API.
85
86 First there is the C<port> function which will create a I<port> and will return
87 it's I<port id>.
88
89 That I<port id> can be used to send and receive messages. That I<port id> is a
90 simple string and can be safely passed to other I<nodes> in the network to
91 refer to that specific port (usually used for RPC, where you need to
92 tell the other end which I<port> to send the reply to).
93
94 Next function is C<rcv>:
95
96 rcv $port, test => sub { ... };
97
98 It sets up a receiver callback on a specific I<port> which needs to be
99 specified as the first argument. The next argument, in this example C<test>, is
100 a I<tag> match. This means that whenever a message, with the first element
101 being the string C<tag>, is received the callback is called with the remaining
102 parts of that message.
103
104 Messages can be send with the C<snd> function, which looks like this in the
105 example above:
106
107 snd $port, test => 123;
108
109 This will send the message C<['test', 123]> to the I<port> with the I<port id>
110 in C<$port>. The receiver got a I<tag> match on C<test> and will call the
111 callback with the first argument being the number C<123>.
112
113 That callback then just passes that number on to the I<condition variable>
114 C<$end_cv> which will then pass the value to the print. But I<condition
115 variables> are out of the scope of this tutorial. So please consult the
116 L<AnyEvent::Intro> about them.
117
118 But passing messages inside one process is boring, but before we can continue
119 and take the next step to interprocess message passing we first have to make
120 sure some things have been setup.
121
122 =head1 System Requirements and System Setup
123
124 Before we can start with real IPC we have to make sure some things work on your
125 system.
126
127 First we have to setup a I<shared secret>: for two L<AnyEvent::MP> I<nodes> to
128 be able to communicate with each other and authenticate each other it is
129 necessary to setup the same I<shared secret> for both of them (or use TLS
130 certificates).
131
132 The easiest way is to set this up is to use the F<aemp> utility:
133
134 aemp gensecret
135
136 This creates a F<$HOME/.perl-anyevent-mp> config file and generates a random
137 shared secret. You can copy this file to any other system and then communicate
138 over the network (via TCP) with it. You can also select your own shared secret
139 (F<aemp setsecret>) and for increased security requirements you can even create
140 a TLS certificate (F<aemp gencert>), causing connections to not just be
141 authenticated, but also to be encrypted.
142
143 Connections will only be successful when the I<nodes> that want to connect to
144 each other have the same I<shared secret> (or successfully verify the TLS
145 certificate of the other side).
146
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
149 that F<~/.perl-anyevent-mp> is the same on all hosts/user accounts that
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.
252
253 =head3 Setting Up The Profiles
254
255 Ok, so much to the profile. Now lets setup the C<eg_simple_receiver> I<profile>
256 for later. For the receiver we just give the receiver a I<bind>:
257
258 aemp profile eg_simple_receiver setbinds localhost:12266
259
260 And while we are at it, just setup the I<profile> for the sender in the second
261 part of this example too. We will call the sender I<profile>
262 C<eg_simple_sender>. For the sender we will just setup a I<seed> to the
263 receiver:
264
265 aemp profile eg_simple_sender setseeds localhost:12266
266
267 You might wonder why we don't setup a I<bind> here. Well, there can be
268 exceptions to the I<fully> in the I<fully connected mesh> in L<AnyEvent::MP>.
269 If you don't configure a I<bind> for a node's profile it won't bind itself
270 somewhere. These kinds of I<nodes> will not be able to send messages to other
271 I<nodes> that also didn't I<bind> them self to some TCP address. For this
272 example, as well as some cases in the real world, we can live with this
273 limitation.
274
275 =head3 Registering The Receiver
276
277 Ok, where were we. We now discussed the basic purpose of L<AnyEvent::MP::Global>
278 and initialise_node with it's relations to profiles. We also setup our profiles
279 for later use and now have to continue talking about the receiver example.
280
281 Lets look at the next undiscussed line(s) of code:
282
283 my $port = port;
284 AnyEvent::MP::Global::register $port, "eg_receivers";
285
286 The C<port> function already has been discussed. It just creates a new I<port>
287 and gives us the I<port id>. Now to the C<register> function of
288 L<AnyEvent::MP::Global>: The first argument is a I<port id> that we want to add
289 to a I<global group>, and it's second argument is the name of that I<global
290 group>.
291
292 You can choose that name of such a I<global group> freely, and it's purpose is
293 to store a set of I<port ids>. That set is made available throughout the whole
294 L<AnyEvent::MP> network, so that each node can see which ports belong to that
295 group.
296
297 The sender will later look for the ports in that I<global group> and send
298 messages to them.
299
300 Last step in the example is to setup a receiver callback for those messages
301 like we have discussed in the first example. We again match for the I<tag>
302 C<test>. The difference is just that we don't end the application after
303 receiving the first message. We just infinitely continue to look out for new
304 messages.
305
306 =head1 The Chat Client
307
308 OK, lets start by implementing the "frontend" of the client. We will
309 develop the client first and postpone the server for later, as the most
310 complex things actually happen in the client.
311
312 We will use L<AnyEvent::Handle> to do non-blocking IO read on standard
313 input (all of this code deals with actually handling user input, no
314 message passing yet):
315
316 #!perl
317
318 use AnyEvent;
319 use AnyEvent::Handle;
320
321 sub send_message {
322 die "This is where we will send the messages to the server"
323 . "in the next step of this tutorial.\n"
324 }
325
326 # make an AnyEvent condition variable for the 'quit' condition
327 # (when we want to exit the client).
328 my $quit_cv = AnyEvent->condvar;
329
330 my $stdin_hdl = AnyEvent::Handle->new (
331 fh => *STDIN,
332 on_error => sub { $quit_cv->send },
333 on_read => sub {
334 my ($hdl) = @_;
335
336 $hdl->push_read (line => sub {
337 my ($hdl, $line) = @_;
338
339 if ($line =~ /^\/quit/) { # /quit will end the client
340 $quit_cv->send;
341 } else {
342 send_message ($line);
343 }
344 });
345 }
346 );
347
348 $quit_cv->recv;
349
350 This is now a very basic client. Explaining explicitly what
351 L<AnyEvent::Handle> does or what a I<condvar> is all about is out of scope
352 of this document, please consult L<AnyEvent::Intro> or the manual pages
353 for L<AnyEvent> and L<AnyEvent::Handle>.
354
355 =head1 First Steps Into Messaging
356
357 To supply the C<send_message> function we now take a look at
358 L<AnyEvent::MP>. This is an example of how it might look like:
359
360 ... # the use lines from the above snippet
361
362 use AnyEvent::MP;
363
364 sub send_message {
365 my ($msg) = @_;
366
367 snd $server_port, message => $msg;
368 }
369
370 ... # the rest of the above script
371
372 The C<snd> function is exported by L<AnyEvent::MP>, it stands for 'send
373 a message'. The first argument is the I<port> (a I<port> is something
374 that can receive messages, represented by a printable string) of the
375 server which will receive the message. How we get this port will be
376 explained in the next step.
377
378 The remaining arguments of C<snd> are C<message> and C<$msg>, the first
379 two elements of the I<message> (a I<message> in L<AnyEvent::MP> is a
380 simple list of values, which can be sent to a I<port>).
381
382 So all the function does is send the two values C<message> (a constant
383 string to tell the server what to expect) and the actual message string.
384
385 Thats all fine and simple so far, but where do we get the
386 C<$server_port>? Well, we need to get the unique I<port id> of the
387 server's port where it wants to receive all the incoming chat messages. A
388 I<port id> is unfortunately a very unique string, which we are unable to
389 know in advance. But L<AnyEvent::MP> supports the concept of 'registered
390 ports', which is basically a port on the server side registered under
391 a well known name.
392
393 For example, the server has a port for receiving chat messages with a
394 unique I<port id> and registers it under the name C<chatter>.
395
396 BTW, these "registered port names" should follow similar rules as Perl
397 identifiers, so you should prefix them with your package/module name to
398 make them unique, unless you use them in the main program.
399
400 As I<messages> can only be sent to a I<port id> and not just to some name
401 we have to ask the server node for the I<port id> of the port registered
402 as C<chatter>.
403
404 =head1 Finding The Chatter Port
405
406 Ok, lots of talk, now some code. Now we will actually get the
407 C<$server_port> from the backend:
408
409 ...
410
411 use AnyEvent::MP;
412
413 my $server_node = "127.0.0.1:1299";
414
415 my $client_port = port;
416
417 snd $server_node, lookup => "chatter", $client_port, "resolved";
418
419 my $resolved_cv = AnyEvent->condvar;
420 my $server_port;
421
422 # setup a receiver callback for the 'resolved' message:
423 rcv $client_port, resolved => sub {
424 my ($tag, $chatter_port_id) = @_;
425
426 print "Resolved the server port 'chatter' to $chatter_port_id\n";
427 $server_port = $chatter_port_id;
428
429 $resolved_cv->send;
430 1
431 };
432
433 # lets block the client until we have resolved the server port.
434 $resolved_cv->recv;
435
436 # now setup another receiver callback for the chat messages:
437 rcv $client_port, message => sub {
438 my ($tag, $msg) = @_;
439
440 print "chat> $msg\n";
441 0
442 };
443
444 # send a 'join' message to the server:
445 snd $server_port, join => "$client_port";
446
447 sub send_message { ...
448
449 Now that was a lot of new stuff:
450
451 First we define the C<$server_node>: In order to refer to another node
452 we need some kind of string to reference it - the node reference. The
453 I<noderef> is basically a comma separated list of C<address:port>
454 pairs. We assume in this tutorial that the server runs on C<127.0.0.1>
455 (localhost) on port 1299, which results in the noderef C<127.0.0.1:1299>.
456
457 Next, in order to receive a reply from the other node or the server we
458 need to have a I<port> that messages can be sent to. This is what the
459 C<port> function will do for us, it just creates a new local port and
460 returns it's I<port ID> that can then be used to receive messages.
461
462 When you look carefully, you will see that the first C<snd> uses the
463 C<$server_node> (a noderef) as destination port. Well, what I didn't
464 tell you yet is that each I<node> has a default I<port> to receive
465 messages. The ID of this port is the same as the noderef.
466
467 This I<default port> provides some special services for us, for example
468 resolving a registered name to a I<port id> (a-ha! finally!).
469
470 This is exactly what this line does:
471
472 snd $server_node, lookup => "chatter", $client_port, "resolved";
473
474 This sends a message with first element being C<lookup>, followed by the
475 (hopefully) registered port name that we want to resolve to a I<port
476 id>: C<chatter>. And in order for the server node to be able to send us
477 back the resolved I<port ID> we have to tell it where to send it: The
478 result message will be sent to C<$client_port> (the I<port id> of the
479 port we just created), and will have the string C<resolved> as the first
480 element.
481
482 When the node receives this message, it will look up the name, gobble up
483 all the extra arguments we passed, append the resolved name, and send the
484 resulting list as a message.
485
486 Next we register a receiver for this C<lookup>-request.
487
488 rcv $client_port, resolved => sub {
489 my ($tag, $chatter_port_id) = @_;
490 ...
491 1
492 };
493
494 This sets up a receiver on our own port for messages with the first
495 element being the string C<resolved>. Receivers can match the contents of
496 the messages before actually executing the specified callback.
497
498 B<Please note> that the every C<rcv> callback has to return either a true
499 or a false value, indicating whether it is B<successful>/B<done> (true) or
500 still wants to B<continue> (false) receiving messages.
501
502 In this case we tell the C<$client_port> to look into all the messages
503 it receives and look for the string C<resolved> in the first element of
504 the message. If it is found, the given callback will be called with the
505 message elements as arguments.
506
507 Using a string as the first element of the message is called I<tagging>
508 the message. It's common practise to code the 'type' of a message into
509 it's first element, as this allows for simple matching.
510
511 The result message will contain the I<port ID> of the well known port
512 C<chatter> as second element, which will be stored in C<$chatter_port_id>.
513
514 This port ID will then be stored in C<$server_port>, followed by calling
515 C<send> on $resolved_cv> so the program will continue.
516
517 The callback then returns a C<1> (a true value), to indicate that it has
518 done it's job and doesn't want to receive further C<resolved> messages.
519
520 After this the chat message receiver callback is registered with the port:
521
522 rcv $client_port, message => sub {
523 my ($tag, $msg) = @_;
524
525 print "chat> $msg\n";
526
527 0
528 };
529
530 We assume that all messages that are broadcast to the clients by the
531 server contain the string tag C<message> as first element, and the actual
532 message as second element. The callback returns a false value this time,
533 to indicate that it is not yet done and wants to receive further messages.
534
535 The last thing to do is to tell the server to send us new chat messages
536 from other clients. We do so by sending the message C<join> followed by
537 our own I<port ID>.
538
539 # send the server a 'join' message:
540 snd $server_port, join => $client_port;
541
542 This way the server knows where to send all the new messages to.
543
544 =head1 The Completed Client
545
546 This is the complete client script:
547
548 #!perl
549
550 use AnyEvent;
551 use AnyEvent::Handle;
552 use AnyEvent::MP;
553
554 my $server_node = "127.0.0.1:1299";
555
556 my $client_port = port;
557
558 snd $server_node, lookup => "chatter", $client_port, "resolved";
559
560 my $resolved_cv = AnyEvent->condvar;
561 my $server_port;
562
563 # setup a receiver callback for the 'resolved' message:
564 rcv $client_port, resolved => sub {
565 my ($tag, $chatter_port_id) = @_;
566
567 print "Resolved the server port 'chatter' to $chatter_port_id\n";
568 $server_port = $chatter_port_id;
569
570 $resolved_cv->send;
571 1
572 };
573
574 # lets block the client until we have resolved the server port.
575 $resolved_cv->recv;
576
577 # now setup another receiver callback for the chat messages:
578 rcv $client_port, message => sub {
579 my ($tag, $msg) = @_;
580
581 print "chat> $msg\n";
582 0
583 };
584
585 # send a 'join' message to the server:
586 snd $server_port, join => "$client_port";
587
588 sub send_message {
589 my ($msg) = @_;
590
591 snd $server_port, message => $msg;
592 }
593
594 # make an AnyEvent condition variable for the 'quit' condition
595 # (when we want to exit the client).
596 my $quit_cv = AnyEvent->condvar;
597
598 my $stdin_hdl = AnyEvent::Handle->new (
599 fh => *STDIN,
600 on_error => sub { $quit_cv->send },
601 on_read => sub {
602 my ($hdl) = @_;
603
604 $hdl->push_read (line => sub {
605 my ($hdl, $line) = @_;
606
607 if ($line =~ /^\/quit/) { # /quit will end the client
608 $quit_cv->send;
609 } else {
610 send_message ($line);
611 }
612 });
613 }
614 );
615
616 $quit_cv->recv;
617
618 =head1 The Server
619
620 Ok, we finally come to the server.
621
622 The server of course also needs to set up a port, and in addition needs to
623 I<register> it, so the clients can find it.
624
625 Again, let's jump directly into the code:
626
627 #!perl
628
629 use AnyEvent;
630 use AnyEvent::MP;
631
632 become_public "127.0.0.1:1299";
633
634 my $chatter_port = port;
635
636 reg $chatter_port, "chatter";
637
638 my %client_ports;
639
640 rcv $chatter_port,
641 join => sub {
642 my ($tag, $client_port) = @_;
643
644 print "got new client port: $client_port\n";
645 $client_ports{$client_port} = 1;
646
647 0
648 },
649 message => sub {
650 my ($tag, $msg) = @_;
651
652 print "message> $msg\n";
653
654 snd $_, message => $msg
655 for keys %client_ports;
656
657 0
658 };
659
660 AnyEvent->condvar->recv;
661
662 That is all. Looks much simpler than the client, doesn't it?
663
664 Let's quickly look over it, as C<rcv> has already been discussed in the
665 client part of this tutorial above.
666
667 First this:
668
669 become_public "127.0.0.1:1299";
670
671 This will tell our I<node> to become a I<public> node, which means that it
672 can be contacted via TCP. The first argument should be the I<noderef> the
673 server wants to be reachable at. In this case it's the TCP port 1299 on
674 C<127.0.0.1>.
675
676 Next we set up two receivers, one for the C<join> messages and another one
677 for the actual messages of type C<messsage>. This is done with a single
678 call to C<rcv>, which allows multiple C<< match => $callback >> pairs.
679
680 In the C<join> callback we receive the client port, which is simply
681 remembered in the C<%client_ports> hash. In the C<message> callback we
682 just iterate through all known C<%client_ports> and relay the message to
683 them.
684
685 That concludes the server.
686
687 =head1 The Remaining Problems
688
689 The implementation as shown still has some bugs. For instance: How does
690 the server know that the client isn't there anymore, so it can clean up
691 the C<%client_ports> hash? Also, the chat messages have no originator, so
692 we don't know who actually sent the message (which would be quite useful
693 for human-to-human interaction: to know who the other one is :).
694
695 But aside from these issues I hope this tutorial showed you the basics of
696 L<AnyEvent::MP> and explained some common idioms.
697
698 How to solve the reliability and C<%client_ports> cleanup problem will
699 be explained later in this tutorial (TODO).
700
701 =head1 Inside The Protocol
702
703 Now, for the interested parties, let me explain some details about the protocol
704 that L<AnyEvent::MP> nodes use to communicate to each other. If you are not
705 interested you can skip this section.
706
707 Usually TCP is used for communication. Each I<node>, if configured to be
708 a I<public> node with the C<initialise_node> function will listen on the
709 configured TCP port (default is 4040).
710
711 If then one I<node> wants to send a message to another I<node> it will
712 connect to the host and port given in the I<port ID>.
713
714 Then some handshaking occurs to check whether both I<nodes> know the
715 I<shared secret>. Optionally, TLS can be enabled (about how to do this
716 exactly please consult the L<AnyEvent::MP> man page, just a hint: It
717 should be enough to put the private key and (self signed) certificate in
718 the C<~/.aemp-secret> file of all nodes).
719
720 After the handshake, messages will be exchanged using a serialiser
721 (usually L<JSON> is used for this, but it is also possible to use other
722 serialization formats such as L<Storable>).
723
724 =head1 SEE ALSO
725
726 L<AnyEvent>
727
728 L<AnyEvent::Handle>
729
730 L<AnyEvent::MP>
731
732 =head1 AUTHOR
733
734 Robin Redeker <elmex@ta-sa.org>
735