… | |
… | |
15 | processes) that use L<AnyEvent::MP> that run either on the same or different |
15 | processes) that use L<AnyEvent::MP> that run either on the same or different |
16 | hosts. |
16 | hosts. |
17 | |
17 | |
18 | In this tutorial I'll show you how to write a simple chat server based on |
18 | In this tutorial I'll show you how to write a simple chat server based on |
19 | L<AnyEvent::MP>. |
19 | L<AnyEvent::MP>. |
|
|
20 | |
|
|
21 | =head2 System Requirements |
|
|
22 | |
|
|
23 | Before we can start we have to make sure some things work on your |
|
|
24 | system. First of all the host C<localhost> should resolve to a local |
|
|
25 | IP address. Next you should be able to do TCP over that address. |
|
|
26 | |
|
|
27 | You should of course also make sure that L<AnyEvent> and L<AnyEvent::MP> |
|
|
28 | are installed. But how to do that is out of scope of this tutorial. |
|
|
29 | |
|
|
30 | Then we have to setup a I<shared secret>. For two L<AnyEvent::MP> nodes |
|
|
31 | to be able to communicate with each other and authenticate each other |
|
|
32 | it is necessary to setup a I<shared secret>. For testing you can write a |
|
|
33 | random string followed by a newline into the file C<.aemp-secret> in your |
|
|
34 | home directory: |
|
|
35 | |
|
|
36 | echo "secret123#4blabla_please_pick_your_own" > ~/.aemp-secret |
|
|
37 | |
|
|
38 | Only if the nodes that want to connect to each other have the same I<shared |
|
|
39 | secret> connections will be successful. |
|
|
40 | |
|
|
41 | B<If something does not work as expected, and for example tcpdump shows |
|
|
42 | that the connections are broken up early, you should make sure that ~/.aemp-secret |
|
|
43 | is the same on both hosts/user accounts you are connecting!> |
20 | |
44 | |
21 | =head2 The Chat Client |
45 | =head2 The Chat Client |
22 | |
46 | |
23 | OK, lets start by implementing the "frontend" of the client. We will delay the |
47 | OK, lets start by implementing the "frontend" of the client. We will delay the |
24 | explanation and the code of the server until we finished the client, as the |
48 | explanation and the code of the server until we finished the client, as the |
… | |
… | |
369 | |
393 | |
370 | This will tell our I<node> to become a I<public> node, which means that it can |
394 | This will tell our I<node> to become a I<public> node, which means that it can |
371 | be contacted via TCP. The first argument should be the I<noderef> the server |
395 | be contacted via TCP. The first argument should be the I<noderef> the server |
372 | wants to be reachable at. In this case it's the TCP port 1299 on localhost. |
396 | wants to be reachable at. In this case it's the TCP port 1299 on localhost. |
373 | |
397 | |
374 | Next we bascially setup two receivers, one for the C<join> messages and |
398 | Next we basically setup two receivers, one for the C<join> messages and |
375 | another one for the actual messages of type C<messsage>. |
399 | another one for the actual messages of type C<messsage>. |
376 | |
400 | |
377 | In the C<join> message we get the client's port, which we just remember in the |
401 | In the C<join> message we get the client's port, which we just remember in the |
378 | C<%client_ports> hash. In the receiver for the message type C<message> we will |
402 | C<%client_ports> hash. In the receiver for the message type C<message> we will |
379 | just iterate through all known C<%client_ports> and relay the message to them. |
403 | just iterate through all known C<%client_ports> and relay the message to them. |
… | |
… | |
389 | for human-to-human interaction: to know who the other one is :). |
413 | for human-to-human interaction: to know who the other one is :). |
390 | |
414 | |
391 | But aside from these issues I hope this tutorial got you the swing of |
415 | But aside from these issues I hope this tutorial got you the swing of |
392 | L<AnyEvent::MP> and explained some common idioms. |
416 | L<AnyEvent::MP> and explained some common idioms. |
393 | |
417 | |
|
|
418 | How to solve the reliability and C<%client_ports> cleanup problem will |
|
|
419 | be explained later in this tutorial (TODO). |
|
|
420 | |
|
|
421 | =head2 Inside The Protocol |
|
|
422 | |
|
|
423 | Now, for the interested parties, let me explain some details about the protocol |
|
|
424 | that L<AnyEvent::MP> nodes use to communicate to each other. If you are not |
|
|
425 | interested you can skip this section. |
|
|
426 | |
|
|
427 | Usually TCP is used for communication. Each I<node>, if configured to be a |
|
|
428 | I<public> node with the C<become_public> function will listen on the configured |
|
|
429 | TCP port (default is usually 4040). |
|
|
430 | |
|
|
431 | If now one I<node> wants to send a message to another I<node> it will connect |
|
|
432 | to the host and port given in the I<port id>. |
|
|
433 | |
|
|
434 | Then some handshaking occurs to check whether both I<nodes> have the same |
|
|
435 | I<shared secret> configured. Optionally even TLS can be enabled (about how to |
|
|
436 | do this exactly please consult the L<AnyEvent::MP> man pages, just a hint: It |
|
|
437 | should be enough to put the private key and (self signed) certificate in the |
|
|
438 | C<~/.aemp-secret> file of all nodes). |
|
|
439 | |
|
|
440 | Now the serialized (usually L<JSON> is used for this, but it is also possible |
|
|
441 | to use other serialization formats, like L<Storable>) messages are sent over |
|
|
442 | the wire using a simple framing protocol. |
|
|
443 | |
394 | =head1 SEE ALSO |
444 | =head1 SEE ALSO |
395 | |
445 | |
396 | L<AnyEvent> |
446 | L<AnyEvent> |
397 | |
447 | |
398 | L<AnyEvent::Handle> |
448 | L<AnyEvent::Handle> |