MESSIP:
Message-Passing over TCP/IP
|
|||
|
|
![]()
![]()
MESSIP implements Message
Passing over TCP/IP, using BSD socket interface programming.
Three kinds of messages can be sent between Processes or Threads:
· Synchronous Messages (blocking messages), from 0 to 64k in size,
· Asynchronous Messages (non blocking, buffered messages), from 0 to 64k in size,
· Timer messages (one shot and repetitive)
Message Passing consist in the exchange of bytes from one task (Process or Thread) to another (Process or Thread), whatever if these tasks are on the same node or on another node over a TCP/IP network.
The task sending the message is known as the client and the task receiving the message is known as the server. In theory, clients and servers do not need a third agent to communicate between themselves, at least for Synchronous Messages (e.g. messages that do not require to be buffered). In practice, to initiate the communication between clients and servers, it’s necessary to have a third task, which is called ‘messip-mgr’ (the messip manager). Only one ‘messip_mgr’ is necessary on a given network. Further versions of messip will enable to have several redundant managers.
A library (shared) provides the messip API functions that enable to talk to either the messip manager or to the other tasks (either clients or servers).
Each process which wants to use Message Passing must first connect to the messip manager, using the next API function: messip_connect. If no IP address and no port is specified (preferred method), then a text file /etc/messip is used. If this file does not exist, then the default IP name ‘localhost’ is used, and the default port 9000 is used.
In order to receive messages, a server must first create a channel (see API function: messip_channel_create). A channel is identified by a name, which must be unique over the whole network. It’s perfectly fine to create several channels for a given process, but because you can receive messages on one specific channel and this operation is (usually) blocking (i.e. you’ll usually wait until you get a message over this channel), in practice a thread will create and manage only a channel at a time. In the future, it will be possible to receive messages on several channels at the same time. Note that you could poll, but it’s often not very efficient.
Prior to send any message to a server (whatever it is a Synchronous or an Asynchronous Message), a client must find the channel. That means that the server must know the name that identifies the channel. In order to be able to further communicate with the server, that’s the only information that the client must know about the server. The API function to be used is: messip_channel_connect.
Both API functions messip_channel_create and messip_channel_connect involve communication with the messip manager (messip-mgr).
A server typically waits for incoming messages, using the next API function: messip_receive. This is normally a blocking function (but you can specify a timeout value), that means that you exit from this function on these events:
· a message has been received (either Synchronous or Asynchronous): each Synchronous message has to be replied, unless you want to keep the client blocked and waiting for an answer.
· timeout has occurred
· a timer has expired
· a client which was connected has either died or closed the connection to the channel.
A client sends either Synchronous or Asynchronous Messages:
· a Synchronous Message is blocking: that means the client will wait until the message is received by the server and processed. The server has to reply to the client in order for the client to be unblocked. Note that you can specify a timeout. Synchronous Messaging do not involve the Messip manager (messip_server agent), only the server and the client talk together. Sending a Synchronous message is performed with the next API function: messip_send
· an Asynchronous Message is non blocking. That means that a client can’t ignore the state of the server. Because of this, there is no reply from the server. Therefore, you can’t assume that the message has been received by the server. When the server has created the channel (where he receive messages), he has specified a parameter which is the maximum number of messages that can be buffered. Asynchronous Message are slower than Synchronous Message because they are copied twice: from the client to the Messip manager, then from the Messip manager to the server.
This is a very simple example, with 2 processes:
· the 1st process create a named channel, in order to receive messages, then wait messages (with a 30 seconds timeout);
· the 2nd process send two Synchronous Messages over this channel (i.e. to the 1st process).
|
// This is the server
#include <stdio.h> #include <stdlib.h> #include <assert.h>
#include "messip.h"
int main( int argc, char *argv[] ) { messip_cnx_t *cnx; messip_channel_t *ch; int32_t type; int index;
// Connexion to the messip manager (use of /etc/messip) messip_init(); if ( !(cnx = messip_connect( NULL, "p1", MESSIP_NOTIMEOUT )) ) return -1;
// Create a channel, in order to receive messages on it ch = messip_channel_create( cnx, “one” , MESSIP_NOTIMEOUT, 0 ); assert( ch != NULL );
// Receive messages for (;;) { index = messip_receive( ch, &type, rec_buff,
sizeof(rec_buff), if (index == MESSIP_MSG_TIMEOUT) break; messip_reply( ch, index, "Bonjour", 8 ); }
return 0; } |
// This is the client
#include <stdio.h> #include <stdlib.h> #include <assert.h>
#include "messip.h"
int main( int argc, char *argv[] ) { messip_cnx_t *cnx; messip_channel_t *ch; char rec_buff[80]; int32_t answer;
// Connexion to the messip manager (use of /etc/messip) messip_init(); if ( !(cnx = messip_connect( NULL, "p2", MESSIP_NOTIMEOUT )) ) return -1;
// Locate the channel where to send message to ch = messip_channel_connect( cnx, “one”, MESSIP_NOTIMEOUT ); assert( ch != NULL );
// Send two messages messip_send( ch, messip_send( ch,
return 0; } |
Resources needed:
· The messip manager (messip-mgr) dynamically creates a new thread to handle each client (whatever it’s a server or a client). There is a new client on each new connection made with messip_connect()
· Also, for the messip manager (messip_server), there is a new thread created for each client to handle Asynchronous Messages (the thread is created on the 1st Asynchronous Message).
· If a server use a timer managed by the library, then a new thread is created when the timer is triggered.
· Both the server and the library must be linked with ‘librt’ that provides some ‘real-time’ extension to Linux, and also with ‘pthread’ (linux).
|
|
Synchronous Messages
|
Asynchronous Messages |
||
|
Machine |
Length (bytes)
of |
Length (bytes)
of |
Number of |
Number of |
|
Machine 1 |
0 |
0 |
49,450 |
21,880 |
|
Machine 1 |
100 |
20 |
47,700 |
20,570 |
|
Machine 1 |
200 |
50 |
47,730 |
|
|
Machine 1 |
1,000 |
200 |
45,100 |
20,710 |
|
Machine 1 |
10,000 |
1,000 |
30,000 |
30,000 |
|
|
Synchronous Messages
|
Asynchronous Messages |
||||
|
Machine |
Machine |
Length (bytes)
of |
Length (bytes)
of |
Number of |
Number of |
|
|
Messip_mgr and
server on the same machine |
Messip_mgr and server not on the same machine |
|||||
|
M1 |
M2 |
0 |
0 |
9,820 |
9,836 |
9,019 |
|
M1 |
M2 |
100 |
20 |
8,085 |
8,063 |
7,730 |
|
M1 |
M2 |
1,000 |
200 |
3,234 |
3,254 |
3,570 |
· Machine 1: Desktop Intel(R) Pentium(R) 4 CPU 2.26GHz
· Machine 2: Laptop Intel(R) Pentium(R) 4 CPU 2.40GHz
· System: Fedora 0.95, kernel 2.6.0-test8
· Network: 100 Mb
Doxygen generated documentation for the library is here.
Doxygen generated documentation for the manager is here.
Please note that only 15% is done so far, the documentation is still a work in progress.
|
Function |
Type |
Prototype |
Description |
|
Server
and Client |
void
messip_init( void );
|
Library
initializations |
|
|
Server
and Client |
messip_cnx_t
* |
Connection
to the messip manager (messip_mgr) |
|
|
Server
and Client |
int |
Disconnection
from the messip manager (messip_mgr) |
|
|
Server |
messip_channel_t
* |
Create
a channel when clients will be able to send messages over. |
|
|
Server |
int |
Delete
a channel that was previously created. Only channel without active
cconnection can be successfully deleted. |
|
|
Client |
messip_channel_t
* |
Enable
a client to connect to the channel owned by a server, in order to send
messages. |
|
|
Client |
int |
Enable
a client to disconnect from a channel. |
|
|
Client |
int |
Ping
the server to check if he can currently process messages. |
|
|
server |
int |
Enable
a server to receive messages: |
|
|
server |
int |
Enable
a server to reply to a client. Note that until the server has replied to the
client, the client is blocked, unless the client has specified a timeout. |
|
|
client |
int |
Enable
a client to send a Synchronous Message to a server. The client will be
blocked until the server has replied. |
|
|
client |
int |
Enable
a client to send an Asynchronous Message to a server. The server will
buffer these messages, until the maximum number of buffered messages is
reached. There is no reply from the server, therefore the client does not wait,
unless the maximum number of buffered messages is reached. |
|
|
server |
timer_t |
Arm a
timer, either one-shot or repetitive. Note that a new thread is created into
the client process when the time is triggered. |
|
|
server |
int |
Delete
a timer previously created. |
|
Function |
Description |
|
MessIP manager. |
Several examples (C code) are provided to demonstrate and
to test the use of the library:
|
Code |
Description |
|
A minimum example to
demonstrate the very basic messaging using a channel:
|
|
|
A more complex example
involving one server and two clients:
|
|
|
Shows the use of timeout
and how to know when a client has disconnected from a channel:
|
|
|
Shows how to use Asynchronous messages |
|
|
This is a performance test
program: the client sends messages to the server for 10 seconds. |
|
|
This example shows how to
use a timer (messages sent automatically using ca timer). |
|
|
|
|
|
Messages sent/received
using several channels. |
|
|
Shows what do to when the
message sent by the client exceeds the size of the receiving buffer on the
server side. |
After your have downloaded the sources code (from SVN), just go into the main directory, and run make:
~/sf/messip$ makeTo compile the examples: