Documentation

Messages

A ZeroMQ message is a discrete unit of data passed between applications or components of the same application. From the point of view of ZeroMQ itself messages are considered to be opaque binary data.

On the wire, ZeroMQ messages are blobs of any size from zero upwards that fit in memory. You do your own serialization using protocol buffers, msgpack, JSON, or whatever else your applications need to speak. It’s wise to choose a data representation that is portable, but you can make your own decisions about trade-offs.

The simplest ZeroMQ message consist of one frame (also called message part). Frames are the basic wire format for ZeroMQ messages. A frame is a length-specified block of data. The length can be zero upwards. ZeroMQ guarantees to deliver all the parts (one or more) for a message, or none of them. This allows you to send or receive a list of frames as a single on-the-wire message.

A message (single or multipart) must fit in memory. If you want to send files of arbitrary sizes, you should break them into pieces and send each piece as separate single-part messages. Using multipart data will not reduce memory consumption.

Working with strings

Passing data as strings is usually the easiest way to get a communication going as serialization is rather straightforward. For ZeroMQ we established the rule that strings are length-specified and are sent on the wire without a trailing null.

The following function sends a string to a socket where the string’s length equals frame’s length.

static void
s_send_string (void *socket, const char *string) {
	zmq_send (socket, strdup(string), strlen(string), 0);
}

To read a string from a socket we have to provide a buffer and its length. The zmq_recv method write as much data into the buffer as possible. If there’s more data it will get discarded. We use the returned frame’s size to set appropriate null-terminator and return a duplicate of the retrieved string.

//  Receive string from socket and convert into C string
//  Chops string at 255 chars, if it's longer
static char *
s_recv_string (void *socket) {
    char buffer [256];
    int size = zmq_recv (socket, buffer, 255, 0);
    if (size == -1)
        return NULL;
    if (size > 255)
        size = 255;
    buffer [size] = \0;
    /* use strndup(buffer, sizeof(buffer)-1) in *nix */
    return strdup (buffer);
}

The following functions sends a C string to a socket as a single-frame message where the string’s length equals frame’s length.

zstr_send (socket, "HELLO");

Another option is to send a formatted string, similar to printf.

zstr_sendf (socket, "%s-%d", "HELLO", 1);

To read a string from a socket simply call the zstr_recv function.

char *string = zstr_recv (socket);

The following function sends a string to a socket.

socket.SendFrame("Hello");

To read a string from a socket simply call the ReceiveFrameString function.

string str = socket.ReceiveFrameString();

The following functions sends a string to a socket as a single-frame message where the string’s length equals frame’s length.

socket.send("HELLO");

To read a string from a socket simply call the recv function.

String hello = socket.recvStr()

If you need more control over the frame itself you use the ZFrame class. The following snippet shows you how to create a frame from a string and send a frame.

ZFrame stringFrame = new ZFrame("HELLO");
stringFrame.send(socket, 0);

The read a frame from a socket and return a ZFrame object call the static recvFrame function on the ZFrame class. If the content is a string you can retrive it by the getString method supplying the charset used to serialize it. By default ZMQ.CHARSET is used for all operations that serialze and deserialize strings.

ZFrame stringFrame = ZFrame.recvFrame(socket);
String hello = stringFrame.getString(ZMQ.CHARSET);

Because we utilise the frame’s length to reflect the string’s length we can send mulitple strings by putting each of them into a seperate frame.

The following function sends an array of string to a socket. The ZMQ_SNDMORE flag tells ZeroMQ to postpone sending until all frames are ready.

static void
s_send_strings (void *socket, const char[] *strings, int no_of_strings) {
    for (index = 0; index < no_of_strings; index++) {
        int FLAG = (index + 1) == no_of_strings ? 0 : ZMQ_SNDMORE;
        zmq_send (socket, strdup(strings[index]), strlen(strings[index]), FLAG);
    }
}

To retrieve a string frames from a multi-part messages we must use the ZMQ_RCVMORE zmq_getsockopt() option after calling zmq_recv() to determine if there are further parts to receive.

char *strings[25];
int rcvmore;
size_t option_len = sizeof (int);
int index = 0;
do {
    strings[index++] = s_recv_string (socket);
    zmq_getsockopt (socket, ZMQ_RCVMORE, &rcvmore, &option_len);
} while (rcvmore);

Sending multiple string frames is possible using the zstr_sendm function. This function will postpone the actually sending of the message until the last frame is ready.

zstr_sendm (socket, "HELLO");
zstr_sendm (socket, "beautiful");
zstr_send (socket, "WORLD!");

Or do the same even simpler with the zstr_sendx function. Last parameter must be NULL!

zstr_sendx (socket, "HELLO", "beautiful", "WORLD!", NULL);

If you like working with message objects rather than building up the message by sending multiple frames. You can use the zmsg class.

zmsg_t *strings = zmsg_new ();
zmsg_addstr ("HELLO");
zmsg_addstr ("beautiful");
zmsg_addstr ("WORLD");
zmsg_send (&strings, socket);

To receive a series of string frames use the zstr_recvx function. Each string is allocated and filled with string data!

char *hello, beautiful, world;
zstr_recvx (socket, &hello, &beautiful, &world, NULL);

Or in case you’re working with zmsg:

zmsg_t *strings = zmsg_recv (socket);
char *hello = zmsg_popstr (strings);
char *beautiful = zmsg_popstr (strings);
char *world = zmsg_popstr (strings);

Sending multiple string frames is possible using the SendMoreFrame function. This function will postpone the actually sending of the message until the last frame is ready.

socket.SendMoreFrame("HELLO")
    .SendMoreFrame("beautiful")
    .SendMore("WORLD!");

To receive a series of strings call ReceiveMultipartStrings function. Which returns a list of strings.

List<string> strings = socket.ReceiveMultipartStrings();

Sending multiple string frames in one message is possible using the sendMore method. This method will postpone the actually sending of the message until the last frame is sent.

socket.sendMore (socket, "HELLO");
socket.sendMore (socket, "beautiful");
socket.send (socket, "WORLD!");

Instead of using the socket’s send API you can construct a multi-frame message using the ZMsg class.

ZMsg *strings = new ZMsg();
strings.add("HELLO");
strings.add("beautiful");
strings.add("WORLD");
strings.send(socket);

To receive a series of string frames call the recvStr function multiple times.

String hello     = socket.recvStr();
String beautiful = socket.recvStr();
String world 	 = socket.recvStr();

In order to retrive the whole message in one call use the static recvMsg method of the ZMsg class.

ZMsg strings = ZMsg.recvMsg(socket);
String hello     = strings.popString();
String beautiful = strings.popString();
String world     = strings.popString();

More

Find out more about working with messages:

  • Working with multi-part messages: zmsg
  • Working with single message frames: zframe,
  • Work with strings: zstr