ÃMQ doesnât know anything about the data you send except its size in bytes. That means you are responsible for formatting it safely so that applications can read it back. Doing this for objects and complex data types is a job for specialized libraries like protocol buffers. But even for strings, you need to take care.
In C and some other languages, strings are terminated with a null byte. We could send a string like âHELLOâ with that extra null byte:
zmq_msg_init_data
(
&
request
,
"Hello"
,
6
,
NULL
,
NULL
);
However, if you send a string from another language, it probably will not include that null byte. For example, when we send that same string in Python, we do this:
socket
.
send
(
"Hello"
)
Then what goes onto the wire is a length (one byte for shorter strings) and the string contents as individual characters (Figure 1-3).
And if you read this from a C program, you will get something that looks like a string, and might by accident act like a string (if by luck the five bytes find themselves followed by an innocently lurking null), but isnât a proper string. When your client and server donât agree on the string format, you will get weird results.
When you receive string data from ÃMQ in C, you simply cannot trust that itâs safely terminated. Every single time you read a string, you should allocate a new buffer with space for an extra byte, copy the string, and terminate it properly with a null.
So letâs establish the rule that ÃMQ strings are length-specified and are sent on the wire without a trailing null. In the simplest case (and weâll do this in our examples), a ÃMQ string maps neatly to a ÃMQ message frame, which looks like the above figureâa length and some bytes.
Here is what we need to do, in C, to receive a ÃMQ string and deliver it to the application as a valid C string:
// Receive 0MQ string from socket and convert into C string
static
char
*
s_recv
(
void
*
socket
)
{
zmq_msg_t
message
;
zmq_msg_init
(
&
message
);
int
size
=
zmq_msg_recv
(
&
message
,
socket
,
0
);
if
(
size
==
-
1
)
return
NULL
;
char
*
string
=
malloc
(
size
+
1
);
memcpy
(
string
,
zmq_msg_data
(
&
message
),
size
);
zmq_msg_close
(
&
message
);
string
[
size
]
=
0
;
return
(
string
);
}
This makes a very handy helper function. In the spirit of
making things we can reuse profitably, we can write a similar
s_send()
function that sends strings in the correct ÃMQ
format and package this into a header file we can reuse.
The result is zhelpers.h, which lets us write sweeter and shorter ÃMQ applications in C. It is a fairly long source, and only fun for C developers, so read it at your leisure.
Get ZeroMQ now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.