/**
@page GRAS_tut_tour_simpleexchange Lesson 2: Exchanging simple messages
\section GRAS_tut_tour_simpleexchange_toc Table of Contents
- \ref GRAS_tut_tour_simpleexchange_msgtype
- \ref GRAS_tut_tour_simpleexchange_socks
- \ref GRAS_tut_tour_simpleexchange_exchange
- \ref GRAS_tut_tour_simpleexchange_recaping
\section GRAS_tut_tour_simpleexchange_msgtype Declaring the messages to be exchanged
We will now see how to exchange messages between hosts. As explained in
section \ref GRAS_tut_intro_model, every GRAS message is (strongly) typed. A
message type is described by its name and the datatype of the data it can
convey. Each process which may exchange a given type of message should
declare it before sending or receiving it. If the description used by the
sender doesn't match the one used by the receiver, you'll get into trouble.
Fortunately, such discrepency will be detected in SG.
We won't convey any payload in this lesson, so we just have to give the name
of message to declare them:
\dontinclude 02-simple.c
\skip gras_msgtype_declare
\until gras_msgtype_declare
Remember that all processes should declare the message types they use.
\section GRAS_tut_tour_simpleexchange_socks Identifying peers you want to communicate with
Then, you need to specify with who you want to communicate. This is done
by opening sockets. GRAS sockets are loosely inspirated by the regular BSD
sockets, but with several simplifications.
If you want to eventually receive messages, you have to open a so-called
server socket. Actually, any GRAS process should open a server socket
since it will allows to identify it uniquely in the system. A socket is
defined by an host name and a port number (just like with BSD sockets).
Since server socket are on the current host, opening a socket to receive
messages on the port 12345 is as easy as:
\skip gras_socket_server
\until gras_socket_server
Hardcoding port numbers that way may lead to difficulties on RL (at least)
since at most one process can listen on a given port. So, if you can, prefer
the \ref gras_socket_server_range, which picks a working port from a range
of value. Of course, if you want your processes to find each others, at
least one port must be hardcoded in the system. Then, any other processes
contact the one listening on that port, which acts as a coordinator.
Our client should also open a server socket, but the picked port don't
matter, so we use:
\skip gras_socket_server
\until gras_socket_server
It will select a port between 1024 (ports below 1024 are reserved under
UNIX) and 10000. You can safely ignore the two last arguments for now and
pass 0.
So, you now know how to create sockets allowing to receive messages. To send
messages, you have to create a so-called client socket. For this, use
\ref gras_socket_client with the hostname and the port of the process you
want to contact as arguments. Our client should simply do:
\dontinclude 02-simple.c
\skip socket_client
\until socket_client
The corresponding server socket must be opened before any client socket can
connect to it. It is thus safe to add a little delay before creating the
client socket. But you cannot use the classical sleep() function for this,
or you will delay the simulator in SG, not your processes. Use \ref
gras_os_sleep instead.
\section GRAS_tut_tour_simpleexchange_exchange Actually exchanging messages
GRAS offers a plenty of ways to communicate. The simple one is to use \ref
gras_msg_send on the sender side, and \ref gras_msg_wait on the receiver side.
\ref gras_msg_send expects 3 arguments: the socket on which to send the
message, the message type (described by its name), and a pointer to the actual content of the
message. Since we don't have any payload, this becomes:
\dontinclude 02-simple.c
\skip msg_send
\until msg_send
\ref gras_msg_wait accepts 4 arguments. The first one is the delay you are
disposed to wait for messages, while the the type of message you are
expecting. Then come output arguments. The third argument should be the
address of a gras_socket_t variable which will indicate who wrote the
message you received while the last argument is where to put the payload.
Since our server is willing to wait up to 60 seconds for a message, the
following will do it:
\dontinclude 02-simple.c
\skip msg_wait
\until msg_wait
\section GRAS_tut_tour_simpleexchange_recaping Recaping everything together
Here is the complete code of this example. Note the use of the functions
\ref gras_socket_my_port, \ref gras_socket_peer_name and \ref
gras_socket_peer_port to retrieve information about who you are connected to.
\include 02-simple.c
Here is the output of the simulator. Note that \ref gras_socket_peer_port
actually returns the port number of the server of the peer. This may
sound a bit strange to BSD experts, but it is actually really useful: you
can store this value, and contact your peer afterward passing this number to
\ref gras_socket_client .
\include 02-simple.output
Here we are, you now know how to exchange messages between peers. There is
still a large room for improvement, such as adding payload to messages. But
there some little things you should know before we speak of payloads.
Go to \ref GRAS_tut_tour_args
*/