SimGrid
Lesson 2: Exchanging simple messages

Table of Contents


Declaring the messages to be exchanged

We will now see how to exchange messages between hosts. As explained in section The model provided by GRAS, 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:

  gras_msgtype_declare("hello", NULL);

Remember that all processes should declare the message types they use.

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:

  mysock = gras_socket_server(12345);

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 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:

  mysock = gras_socket_server_range(1024, 10000, 0, 0);

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 gras_socket_client with the hostname and the port of the process you want to contact as arguments. Our client should simply do:

  toserver = gras_socket_client("Jacquelin", 12345);

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 gras_os_sleep instead.

Actually exchanging messages

GRAS offers a plenty of ways to communicate. The simple one is to use gras_msg_send on the sender side, and gras_msg_wait on the receiver side.

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:

  gras_msg_send(toserver, "hello", NULL);

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:

  gras_msg_wait(60, "hello", &toclient, NULL /* no payload */ );

Recaping everything together

Here is the complete code of this example. Note the use of the functions gras_socket_my_port, gras_socket_peer_name and gras_socket_peer_port to retrieve information about who you are connected to.

/* Copyright (c) 2006, 2007, 2010. The SimGrid Team.
 * All rights reserved.                                                     */

/* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */

#include <stdio.h>
#include <gras.h>

int server(int argc, char *argv[])
{
  gras_socket_t mysock;         /* socket on which I listen */
  gras_socket_t toclient;       /* socket used to write to the client */

  gras_init(&argc, argv);

  gras_msgtype_declare("hello", NULL);
  mysock = gras_socket_server(12345);

  gras_msg_wait(60, "hello", &toclient, NULL /* no payload */ );

  fprintf(stderr, "Cool, we received the message from %s:%d.\n",
          gras_socket_peer_name(toclient),
          gras_socket_peer_port(toclient));

  gras_exit();
  return 0;
}

int client(int argc, char *argv[])
{
  gras_socket_t mysock;         /* socket on which I listen */
  gras_socket_t toserver;       /* socket used to write to the server */

  gras_init(&argc, argv);

  gras_msgtype_declare("hello", NULL);
  mysock = gras_socket_server_range(1024, 10000, 0, 0);

  fprintf(stderr, "Client ready; listening on %d\n",
          gras_socket_my_port(mysock));

  gras_os_sleep(1.5);           /* sleep 1 second and half */
  toserver = gras_socket_client("Jacquelin", 12345);

  gras_msg_send(toserver, "hello", NULL);
  fprintf(stderr, "That's it, we sent the data to the server\n");

  gras_exit();
  return 0;
}

Here is the output of the simulator. Note that 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 gras_socket_client .

$ ./test_simulator platform.xml test.xml
Client ready; listening on 1024
That's it, we sent the data to the server
[Boivin:client:(2) 0.000000] [gras/INFO] Exiting GRAS
Cool, we received the message from Boivin:1024.
[Jacquelin:server:(1) 0.000000] [gras/INFO] Exiting GRAS
$

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 Lesson 3: Passing arguments to the processes (in SG)


Back to the main Simgrid Documentation page The version of Simgrid documented here is v3.6.1.
Documentation of other versions can be found in their respective archive files (directory doc/html).
Generated for SimGridAPI by doxygen