zmsg(3) ======= NAME ---- zmsg - working with multipart messages SYNOPSIS -------- ---- // Create a new empty message object CZMQ_EXPORT zmsg_t * zmsg_new (void); // Destroy a message object and all frames it contains CZMQ_EXPORT void zmsg_destroy (zmsg_t **self_p); // Receive message from socket, returns zmsg_t object or NULL if the recv // was interrupted. Does a blocking recv, if you want to not block then use // the zloop class or zmq_poll to check for socket input before receiving. CZMQ_EXPORT zmsg_t * zmsg_recv (void *socket); // Send message to socket, destroy after sending. If the message has no // frames, sends nothing but destroys the message anyhow. Safe to call // if zmsg is null. CZMQ_EXPORT int zmsg_send (zmsg_t **self_p, void *socket); // Return size of message, i.e. number of frames (0 or more). CZMQ_EXPORT size_t zmsg_size (zmsg_t *self); // Return total size of all frames in message. CZMQ_EXPORT size_t zmsg_content_size (zmsg_t *self); // Push frame to the front of the message, i.e. before all other frames. // Message takes ownership of frame, will destroy it when message is sent. // Returns 0 on success, -1 on error. CZMQ_EXPORT int zmsg_push (zmsg_t *self, zframe_t *frame); // Remove first frame from message, if any. Returns frame, or NULL. Caller // now owns frame and must destroy it when finished with it. CZMQ_EXPORT zframe_t * zmsg_pop (zmsg_t *self); // Add frame to the end of the message, i.e. after all other frames. // Message takes ownership of frame, will destroy it when message is sent. // Returns 0 on success. Deprecates zmsg_add, which did not nullify the // caller's frame reference. CZMQ_EXPORT int zmsg_append (zmsg_t *self, zframe_t **frame_p); // Add frame to the end of the message, i.e. after all other frames. // Message takes ownership of frame, will destroy it when message is sent. // Returns 0 on success. // DEPRECATED - will be removed for next stable release CZMQ_EXPORT int zmsg_add (zmsg_t *self, zframe_t *frame); // Push block of memory to front of message, as a new frame. // Returns 0 on success, -1 on error. CZMQ_EXPORT int zmsg_pushmem (zmsg_t *self, const void *src, size_t size); // Add block of memory to the end of the message, as a new frame. // Returns 0 on success, -1 on error. CZMQ_EXPORT int zmsg_addmem (zmsg_t *self, const void *src, size_t size); // Push string as new frame to front of message. // Returns 0 on success, -1 on error. CZMQ_EXPORT int zmsg_pushstr (zmsg_t *self, const char *format, ...); // Push string as new frame to end of message. // Returns 0 on success, -1 on error. CZMQ_EXPORT int zmsg_addstr (zmsg_t *self, const char *format, ...); // Pop frame off front of message, return as fresh string. If there were // no more frames in the message, returns NULL. CZMQ_EXPORT char * zmsg_popstr (zmsg_t *self); // Push frame plus empty frame to front of message, before first frame. // Message takes ownership of frame, will destroy it when message is sent. CZMQ_EXPORT void zmsg_wrap (zmsg_t *self, zframe_t *frame); // Pop frame off front of message, caller now owns frame // If next frame is empty, pops and destroys that empty frame. CZMQ_EXPORT zframe_t * zmsg_unwrap (zmsg_t *self); // Remove specified frame from list, if present. Does not destroy frame. CZMQ_EXPORT void zmsg_remove (zmsg_t *self, zframe_t *frame); // Set cursor to first frame in message. Returns frame, or NULL, if the // message is empty. Use this to navigate the frames as a list. CZMQ_EXPORT zframe_t * zmsg_first (zmsg_t *self); // Return the next frame. If there are no more frames, returns NULL. To move // to the first frame call zmsg_first(). Advances the cursor. CZMQ_EXPORT zframe_t * zmsg_next (zmsg_t *self); // Return the last frame. If there are no frames, returns NULL. CZMQ_EXPORT zframe_t * zmsg_last (zmsg_t *self); // Save message to an open file, return 0 if OK, else -1. The message is // saved as a series of frames, each with length and data. Note that the // file is NOT guaranteed to be portable between operating systems, not // versions of CZMQ. The file format is at present undocumented and liable // to arbitrary change. CZMQ_EXPORT int zmsg_save (zmsg_t *self, FILE *file); // Load/append an open file into message, create new message if // null message provided. Returns NULL if the message could not // be loaded. CZMQ_EXPORT zmsg_t * zmsg_load (zmsg_t *self, FILE *file); // Serialize multipart message to a single buffer. Use this method to send // structured messages across transports that do not support multipart data. // Allocates and returns a new buffer containing the serialized message. // To decode a serialized message buffer, use zmsg_decode (). CZMQ_EXPORT size_t zmsg_encode (zmsg_t *self, byte **buffer); // Decodes a serialized message buffer created by zmsg_encode () and returns // a new zmsg_t object. Returns NULL if the buffer was badly formatted or // there was insufficient memory to work. CZMQ_EXPORT zmsg_t * zmsg_decode (byte *buffer, size_t buffer_size); // Create copy of message, as new message object. Returns a fresh zmsg_t // object, or NULL if there was not enough heap memory. CZMQ_EXPORT zmsg_t * zmsg_dup (zmsg_t *self); // Dump message to stderr, for debugging and tracing. // See zmsg_dump_to_stream() for details CZMQ_EXPORT void zmsg_dump (zmsg_t *self); // Dump message to FILE stream, for debugging and tracing. // Truncates to first 10 frames, for readability; this may be unfortunate // when debugging larger and more complex messages. CZMQ_EXPORT void zmsg_dump_to_stream (zmsg_t *self, FILE *file); // Self test of this class CZMQ_EXPORT int zmsg_test (bool verbose); ---- DESCRIPTION ----------- The zmsg class provides methods to send and receive multipart messages across 0MQ sockets. This class provides a list-like container interface, with methods to work with the overall container. zmsg_t messages are composed of zero or more zframe_t frames. EXAMPLE ------- .From zmsg_test method ---- zctx_t *ctx = zctx_new (); assert (ctx); void *output = zsocket_new (ctx, ZMQ_PAIR); assert (output); zsocket_bind (output, "inproc://zmsg.test"); void *input = zsocket_new (ctx, ZMQ_PAIR); assert (input); zsocket_connect (input, "inproc://zmsg.test"); // Test send and receive of single-frame message zmsg_t *msg = zmsg_new (); assert (msg); zframe_t *frame = zframe_new ("Hello", 5); assert (frame); zmsg_push (msg, frame); assert (zmsg_size (msg) == 1); assert (zmsg_content_size (msg) == 5); rc = zmsg_send (&msg, output); assert (msg == NULL); assert (rc == 0); msg = zmsg_recv (input); assert (msg); assert (zmsg_size (msg) == 1); assert (zmsg_content_size (msg) == 5); zmsg_destroy (&msg); // Test send and receive of multi-frame message msg = zmsg_new (); assert (msg); rc = zmsg_addmem (msg, "Frame0", 6); assert (rc == 0); rc = zmsg_addmem (msg, "Frame1", 6); assert (rc == 0); rc = zmsg_addmem (msg, "Frame2", 6); assert (rc == 0); rc = zmsg_addmem (msg, "Frame3", 6); assert (rc == 0); rc = zmsg_addmem (msg, "Frame4", 6); assert (rc == 0); rc = zmsg_addmem (msg, "Frame5", 6); assert (rc == 0); rc = zmsg_addmem (msg, "Frame6", 6); assert (rc == 0); rc = zmsg_addmem (msg, "Frame7", 6); assert (rc == 0); rc = zmsg_addmem (msg, "Frame8", 6); assert (rc == 0); rc = zmsg_addmem (msg, "Frame9", 6); assert (rc == 0); zmsg_t *copy = zmsg_dup (msg); assert (copy); rc = zmsg_send (©, output); assert (rc == 0); rc = zmsg_send (&msg, output); assert (rc == 0); copy = zmsg_recv (input); assert (copy); assert (zmsg_size (copy) == 10); assert (zmsg_content_size (copy) == 60); zmsg_destroy (©); msg = zmsg_recv (input); assert (msg); assert (zmsg_size (msg) == 10); assert (zmsg_content_size (msg) == 60); // create empty file for null test FILE *file = fopen ("zmsg.test", "w"); assert (file); fclose (file); file = fopen ("zmsg.test", "r"); zmsg_t *null_msg = zmsg_load (NULL, file); assert (null_msg == NULL); fclose (file); remove ("zmsg.test"); // Save to a file, read back file = fopen ("zmsg.test", "w"); assert (file); rc = zmsg_save (msg, file); assert (rc == 0); fclose (file); file = fopen ("zmsg.test", "r"); rc = zmsg_save (msg, file); assert (rc == -1); fclose (file); zmsg_destroy (&msg); file = fopen ("zmsg.test", "r"); msg = zmsg_load (NULL, file); assert (msg); fclose (file); remove ("zmsg.test"); assert (zmsg_size (msg) == 10); assert (zmsg_content_size (msg) == 60); // Remove all frames except first and last int frame_nbr; for (frame_nbr = 0; frame_nbr < 8; frame_nbr++) { zmsg_first (msg); frame = zmsg_next (msg); zmsg_remove (msg, frame); zframe_destroy (&frame); } // Test message frame manipulation assert (zmsg_size (msg) == 2); frame = zmsg_last (msg); assert (zframe_streq (frame, "Frame9")); assert (zmsg_content_size (msg) == 12); frame = zframe_new ("Address", 7); assert (frame); zmsg_wrap (msg, frame); assert (zmsg_size (msg) == 4); rc = zmsg_addstr (msg, "Body"); assert (rc == 0); assert (zmsg_size (msg) == 5); frame = zmsg_unwrap (msg); zframe_destroy (&frame); assert (zmsg_size (msg) == 3); char *body = zmsg_popstr (msg); assert (streq (body, "Frame0")); free (body); zmsg_destroy (&msg); // Test encoding/decoding msg = zmsg_new (); assert (msg); byte *blank = (byte *) zmalloc (100000); assert (blank); rc = zmsg_addmem (msg, blank, 0); assert (rc == 0); rc = zmsg_addmem (msg, blank, 1); assert (rc == 0); rc = zmsg_addmem (msg, blank, 253); assert (rc == 0); rc = zmsg_addmem (msg, blank, 254); assert (rc == 0); rc = zmsg_addmem (msg, blank, 255); assert (rc == 0); rc = zmsg_addmem (msg, blank, 256); assert (rc == 0); rc = zmsg_addmem (msg, blank, 65535); assert (rc == 0); rc = zmsg_addmem (msg, blank, 65536); assert (rc == 0); rc = zmsg_addmem (msg, blank, 65537); assert (rc == 0); free (blank); assert (zmsg_size (msg) == 9); byte *buffer; size_t buffer_size = zmsg_encode (msg, &buffer); zmsg_destroy (&msg); msg = zmsg_decode (buffer, buffer_size); assert (msg); free (buffer); zmsg_destroy (&msg); // Now try methods on an empty message msg = zmsg_new (); assert (msg); assert (zmsg_size (msg) == 0); assert (zmsg_unwrap (msg) == NULL); assert (zmsg_first (msg) == NULL); assert (zmsg_last (msg) == NULL); assert (zmsg_next (msg) == NULL); assert (zmsg_pop (msg) == NULL); assert (zmsg_send (&msg, output) == -1); assert (msg != NULL); zmsg_destroy (&msg); zctx_destroy (&ctx); ---- SEE ALSO -------- linkczmq:czmq[7]