1ZFRAME(3)                         CZMQ Manual                        ZFRAME(3)
2
3
4

NAME

6       zframe - Class for working with single message frames
7

SYNOPSIS

9       //  This is a stable class, and may not change except for emergencies. It
10       //  is provided in stable builds.
11       //  This class has draft methods, which may change over time. They are not
12       //  in stable releases, by default. Use --enable-drafts to enable.
13       #define ZFRAME_MORE 1                        //
14       #define ZFRAME_REUSE 2                       //
15       #define ZFRAME_DONTWAIT 4                    //
16
17       //  Create a new frame. If size is not null, allocates the frame data
18       //  to the specified size. If additionally, data is not null, copies
19       //  size octets from the specified data into the frame body.
20       CZMQ_EXPORT zframe_t *
21           zframe_new (const void *data, size_t size);
22
23       //  Create an empty (zero-sized) frame
24       CZMQ_EXPORT zframe_t *
25           zframe_new_empty (void);
26
27       //  Create a frame with a specified string content.
28       CZMQ_EXPORT zframe_t *
29           zframe_from (const char *string);
30
31       //  Receive frame from socket, returns zframe_t object or NULL if the recv
32       //  was interrupted. Does a blocking recv, if you want to not block then use
33       //  zpoller or zloop.
34       CZMQ_EXPORT zframe_t *
35           zframe_recv (void *source);
36
37       //  Destroy a frame
38       CZMQ_EXPORT void
39           zframe_destroy (zframe_t **self_p);
40
41       //  Send a frame to a socket, destroy frame after sending.
42       //  Return -1 on error, 0 on success.
43       CZMQ_EXPORT int
44           zframe_send (zframe_t **self_p, void *dest, int flags);
45
46       //  Return number of bytes in frame data
47       CZMQ_EXPORT size_t
48           zframe_size (zframe_t *self);
49
50       //  Return address of frame data
51       CZMQ_EXPORT byte *
52           zframe_data (zframe_t *self);
53
54       //  Return meta data property for frame
55       //  The caller shall not modify or free the returned value, which shall be
56       //  owned by the message.
57       CZMQ_EXPORT const char *
58           zframe_meta (zframe_t *self, const char *property);
59
60       //  Create a new frame that duplicates an existing frame. If frame is null,
61       //  or memory was exhausted, returns null.
62       //  Caller owns return value and must destroy it when done.
63       CZMQ_EXPORT zframe_t *
64           zframe_dup (zframe_t *self);
65
66       //  Return frame data encoded as printable hex string, useful for 0MQ UUIDs.
67       //  Caller must free string when finished with it.
68       //  Caller owns return value and must destroy it when done.
69       CZMQ_EXPORT char *
70           zframe_strhex (zframe_t *self);
71
72       //  Return frame data copied into freshly allocated string
73       //  Caller must free string when finished with it.
74       //  Caller owns return value and must destroy it when done.
75       CZMQ_EXPORT char *
76           zframe_strdup (zframe_t *self);
77
78       //  Return TRUE if frame body is equal to string, excluding terminator
79       CZMQ_EXPORT bool
80           zframe_streq (zframe_t *self, const char *string);
81
82       //  Return frame MORE indicator (1 or 0), set when reading frame from socket
83       //  or by the zframe_set_more() method
84       CZMQ_EXPORT int
85           zframe_more (zframe_t *self);
86
87       //  Set frame MORE indicator (1 or 0). Note this is NOT used when sending
88       //  frame to socket, you have to specify flag explicitly.
89       CZMQ_EXPORT void
90           zframe_set_more (zframe_t *self, int more);
91
92       //  Return TRUE if two frames have identical size and data
93       //  If either frame is NULL, equality is always false.
94       CZMQ_EXPORT bool
95           zframe_eq (zframe_t *self, zframe_t *other);
96
97       //  Set new contents for frame
98       CZMQ_EXPORT void
99           zframe_reset (zframe_t *self, const void *data, size_t size);
100
101       //  Send message to zsys log sink (may be stdout, or system facility as
102       //  configured by zsys_set_logstream). Prefix shows before frame, if not null.
103       //  Long messages are truncated.
104       CZMQ_EXPORT void
105           zframe_print (zframe_t *self, const char *prefix);
106
107       //  Probe the supplied object, and report if it looks like a zframe_t.
108       CZMQ_EXPORT bool
109           zframe_is (void *self);
110
111       //  Self test of this class.
112       CZMQ_EXPORT void
113           zframe_test (bool verbose);
114
115       #ifdef CZMQ_BUILD_DRAFT_API
116       // Destroy an item
117       typedef void (zframe_destructor_fn) (
118           void **hint);
119
120       //  *** Draft method, for development use, may change without warning ***
121       //  Create a new frame from memory. Take ownership of the memory and calling the destructor
122       //  on destroy.
123       CZMQ_EXPORT zframe_t *
124           zframe_frommem (void *data, size_t size, zframe_destructor_fn destructor, void *hint);
125
126       //  *** Draft method, for development use, may change without warning ***
127       //  Return frame routing ID, if the frame came from a ZMQ_SERVER socket.
128       //  Else returns zero.
129       CZMQ_EXPORT uint32_t
130           zframe_routing_id (zframe_t *self);
131
132       //  *** Draft method, for development use, may change without warning ***
133       //  Set routing ID on frame. This is used if/when the frame is sent to a
134       //  ZMQ_SERVER socket.
135       CZMQ_EXPORT void
136           zframe_set_routing_id (zframe_t *self, uint32_t routing_id);
137
138       //  *** Draft method, for development use, may change without warning ***
139       //  Return frame group of radio-dish pattern.
140       CZMQ_EXPORT const char *
141           zframe_group (zframe_t *self);
142
143       //  *** Draft method, for development use, may change without warning ***
144       //  Set group on frame. This is used if/when the frame is sent to a
145       //  ZMQ_RADIO socket.
146       //  Return -1 on error, 0 on success.
147       CZMQ_EXPORT int
148           zframe_set_group (zframe_t *self, const char *group);
149
150       //  *** Draft method, for development use, may change without warning ***
151       //  Send message to zsys log sink (may be stdout, or system facility as
152       //  configured by zsys_set_logstream). Prefix shows before frame, if not null.
153       //  Message length is specified; no truncation unless length is zero.
154       //  Backwards compatible with zframe_print when length is zero.
155       CZMQ_EXPORT void
156           zframe_print_n (zframe_t *self, const char *prefix, size_t length);
157
158       #endif // CZMQ_BUILD_DRAFT_API
159       Please add '@interface' section in './../src/zframe.c'.
160

DESCRIPTION

162       The zframe class provides methods to send and receive single message
163       frames across 0MQ sockets. A frame corresponds to one zmq_msg_t. When
164       you read a frame from a socket, the zframe_more() method indicates if
165       the frame is part of an unfinished multipart message. The zframe_send
166       method normally destroys the frame, but with the ZFRAME_REUSE flag, you
167       can send the same frame many times. Frames are binary, and this class
168       has no special support for text data.
169
170       Please add @discuss section in ./../src/zframe.c.
171

EXAMPLE

173       From zframe_test method.
174
175           //  Create two PAIR sockets and connect over TCP
176           zsock_t *output = zsock_new (ZMQ_PAIR);
177           assert (output);
178           int port = zsock_bind (output, "tcp://127.0.0.1:*");
179           assert (port != -1);
180           zsock_t *input = zsock_new (ZMQ_PAIR);
181           assert (input);
182           rc = zsock_connect (input, "tcp://127.0.0.1:%d", port);
183           assert (rc != -1);
184
185           //  Send five different frames, test ZFRAME_MORE
186           int frame_nbr;
187           for (frame_nbr = 0; frame_nbr < 5; frame_nbr++) {
188               frame = zframe_new ("Hello", 5);
189               assert (frame);
190               rc = zframe_send (&frame, output, ZFRAME_MORE);
191               assert (rc == 0);
192           }
193           //  Send same frame five times, test ZFRAME_REUSE
194           frame = zframe_new ("Hello", 5);
195           assert (frame);
196           for (frame_nbr = 0; frame_nbr < 5; frame_nbr++) {
197               rc = zframe_send (&frame, output, ZFRAME_MORE + ZFRAME_REUSE);
198               assert (rc == 0);
199           }
200           assert (frame);
201           zframe_t *copy = zframe_dup (frame);
202           assert (zframe_eq (frame, copy));
203           zframe_destroy (&frame);
204           assert (!zframe_eq (frame, copy));
205           assert (zframe_size (copy) == 5);
206           zframe_destroy (&copy);
207           assert (!zframe_eq (frame, copy));
208
209           //  Test zframe_new_empty
210           frame = zframe_new_empty ();
211           assert (frame);
212           assert (zframe_size (frame) == 0);
213           zframe_destroy (&frame);
214
215           //  Send END frame
216           frame = zframe_new ("NOT", 3);
217           assert (frame);
218           zframe_reset (frame, "END", 3);
219           char *string = zframe_strhex (frame);
220           assert (streq (string, "454E44"));
221           freen (string);
222           string = zframe_strdup (frame);
223           assert (streq (string, "END"));
224           freen (string);
225           rc = zframe_send (&frame, output, 0);
226           assert (rc == 0);
227
228           //  Read and count until we receive END
229           frame_nbr = 0;
230           for (frame_nbr = 0;; frame_nbr++) {
231               zframe_t *frame = zframe_recv (input);
232               if (zframe_streq (frame, "END")) {
233                   zframe_destroy (&frame);
234                   break;
235               }
236               assert (zframe_more (frame));
237               zframe_set_more (frame, 0);
238               assert (zframe_more (frame) == 0);
239               zframe_destroy (&frame);
240           }
241           assert (frame_nbr == 10);
242
243           #if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (4, 1, 0))
244           // Test zframe_meta
245           frame = zframe_new ("Hello", 5);
246           assert (frame);
247           rc = zframe_send (&frame, output, 0);
248           assert (rc == 0);
249           frame = zframe_recv (input);
250           const char *meta = zframe_meta (frame, "Socket-Type");
251           assert (meta != NULL);
252           assert (streq (meta, "PAIR"));
253           assert (zframe_meta (frame, "nonexistent") == NULL);
254           zframe_destroy (&frame);
255           #endif
256
257           zsock_destroy (&input);
258           zsock_destroy (&output);
259
260           #if defined (ZMQ_SERVER)
261           //  Create server and client sockets and connect over inproc
262           zsock_t *server = zsock_new_server ("inproc://zframe-test-routing");
263           assert (server);
264           zsock_t *client = zsock_new_client ("inproc://zframe-test-routing");
265           assert (client);
266
267           //  Send request from client to server
268           zframe_t *request = zframe_new ("Hello", 5);
269           assert (request);
270           rc = zframe_send (&request, client, 0);
271           assert (rc == 0);
272           assert (!request);
273
274           //  Read request and send reply
275           request = zframe_recv (server);
276           assert (request);
277           assert (zframe_streq (request, "Hello"));
278           assert (zframe_routing_id (request));
279
280           zframe_t *reply = zframe_new ("World", 5);
281           assert (reply);
282           zframe_set_routing_id (reply, zframe_routing_id (request));
283           rc = zframe_send (&reply, server, 0);
284           assert (rc == 0);
285           zframe_destroy (&request);
286
287           //  Read reply
288           reply = zframe_recv (client);
289           assert (zframe_streq (reply, "World"));
290           assert (zframe_routing_id (reply) == 0);
291           zframe_destroy (&reply);
292
293           //  Client and server disallow multipart
294           frame = zframe_new ("Hello", 5);
295           rc = zframe_send (&frame, client, ZFRAME_MORE);
296           assert (rc == -1);
297           rc = zframe_send (&frame, server, ZFRAME_MORE);
298           assert (rc == -1);
299           zframe_destroy (&frame);
300
301           zsock_destroy (&client);
302           zsock_destroy (&server);
303           #endif
304
305           #ifdef ZMQ_RADIO
306           //  Create radio and dish sockets and connect over inproc
307           zsock_t *radio = zsock_new_radio ("inproc://zframe-test-radio");
308           assert (radio);
309           zsock_t *dish = zsock_new_dish ("inproc://zframe-test-radio");
310           assert (dish);
311
312           //  Join the group
313           rc = zsock_join (dish, "World");
314           assert (rc == 0);
315
316           //  Publish message from radio
317           zframe_t *message = zframe_new ("Hello", 5);
318           assert (message);
319           rc = zframe_set_group (message, "World");
320           assert (rc == 0);
321           rc = zframe_send (&message, radio, 0);
322           assert (rc == 0);
323           assert (!message);
324
325           //  Receive the message from dish
326           message = zframe_recv (dish);
327           assert (message);
328           assert (zframe_streq (message, "Hello"));
329           assert (strcmp("World", zframe_group (message)) == 0);
330           zframe_destroy (&message);
331
332           zsock_destroy (&dish);
333           zsock_destroy (&radio);
334           #else
335           frame = zframe_new ("Hello", 5);
336           rc = zframe_set_group (frame, "World");
337           assert(rc == -1);
338           assert(errno == ENOTSUP);
339           zframe_destroy (&frame);
340           #endif
341
342           char str[] = "hello";
343           frame = zframe_frommem (str, 5, mem_destructor, str);
344           assert (frame);
345           zframe_destroy (&frame);
346
347           //  The destructor doesn't free the memory, only changing the strid,
348           //  so we can check if the destructor was invoked
349           assert (streq (str, "world"));
350
351
352           // zframe_print tests
353
354           zsys_set_logstream(verbose ? stdout : NULL);
355
356           // == No data ==
357           frame = zframe_new ("", 0);
358
359           // no prefix, backwards compatible
360           //  - emits nothing but the timestamp
361           zframe_print (frame, "");
362           zframe_print_n (frame, "", 0);
363
364           // prefix, backwards compatible
365           //  - emits nothing but the timestamp
366           zframe_print (frame, "Prefix");
367           zframe_print_n (frame, "Prefix", 0);
368
369           // len > data
370           //  - emits nothing but the timestamp
371           zframe_print_n (frame, "", 15);
372           zframe_print_n (frame, "Prefix", 15);
373
374           // max len
375           //  - emits nothing but the timestamp
376           zframe_print_n (frame, "", -1);
377           zframe_print_n (frame, "Prefix", -1);
378
379           zframe_destroy (&frame);
380
381
382           // == Short data ==
383           frame = zframe_new ("Hello there!", 12);
384
385           // no prefix, backwards compatible: ellipsis
386           //  - "[012] Hello there!"
387           zframe_print (frame, "");
388           zframe_print_n (frame, "", 0);
389
390           // prefix, backwards compatible: ellipsis
391           //  - "Prefix[012] Hello there!"
392           zframe_print (frame, "Prefix");
393           zframe_print_n (frame, "Prefix", 0);
394
395           // len < data
396           //  - "[012] Hello"
397           //  - "Prefix[012] Hello"
398           zframe_print_n (frame, "", 5);
399           zframe_print_n (frame, "Prefix", 5);
400
401           // len > data
402           //  - "[012] Hello there!"
403           //  - "Prefix[012] Hello there!"
404           zframe_print_n (frame, "", 15);
405           zframe_print_n (frame, "Prefix", 15);
406
407           // max len
408           //  - "[012] Hello there!"
409           //  - "Prefix[012] Hello there!"
410           zframe_print_n (frame, "", -1);
411           zframe_print_n (frame, "Prefix", -1);
412
413           zframe_destroy (&frame);
414
415
416           // == Long data ==
417           frame = zframe_new ("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus ligula et aliquam tristique. Phasellus consequat, enim et blandit varius, sapien diam faucibus lorem, non ultricies lacus turpis sed lectus. Vivamus id elit urna. In sit amet lacinia mauris. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer ut cursus diam. Vestibulum semper vel leo eu finibus. Ut urna magna, commodo vel auctor sed, eleifend quis lacus. Aenean quis ipsum et velit auctor ultrices.", 519);
418
419           // no prefix, backwards compatible: ellipsis
420           //  - "[070] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus..."
421           zframe_print (frame, "");
422           zframe_print_n (frame, "", 0);
423
424           // prefix, backwards compatible: ellipsis
425           //  - "Prefix[070] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus..."
426           zframe_print (frame, "Prefix");
427           zframe_print_n (frame, "Prefix", 0);
428
429           // len < data
430           //  - "[519] Lorem"
431           //  - "Prefix[519] Lorem"
432           zframe_print_n (frame, "", 5);
433           zframe_print_n (frame, "Prefix", 5);
434
435           // small len
436           //  - "[519] Lorem ipsum dolor sit amet"
437           //  - "Prefix[519] Lorem ipsum dolor sit amet"
438           zframe_print_n (frame, "", 26);
439           zframe_print_n (frame, "Prefix", 26);
440
441           // mid len
442           // - "[519] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus"
443           //   "[519]  ligula et aliquam tristique. Phasellus consequat, enim et blandit var"
444           //   "[519] ius, sapie"
445           // - "Prefix[519] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus"
446           //   "Prefix[519]  ligula et aliquam tristique. Phasellus consequat, enim et blandit var"
447           //   "Prefix[519] ius, sapie"
448           zframe_print_n (frame, "", 150);
449           zframe_print_n (frame, "Prefix", 150);
450
451           // len > data
452           //  - emits the whole paragraph
453           zframe_print_n (frame, "", 1500);
454           zframe_print_n (frame, "Prefix", 1500);
455
456           // max len
457           //  - emits the whole paragraph
458           zframe_print_n (frame, "", -1);
459           zframe_print_n (frame, "Prefix", -1);
460
461           zframe_destroy (&frame);
462
463           #if defined (__WINDOWS__)
464           zsys_shutdown();
465           #endif
466
467

AUTHORS

469       The czmq manual was written by the authors in the AUTHORS file.
470

RESOURCES

472       Main web site:
473
474       Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>
475
477       Copyright (c) the Contributors as noted in the AUTHORS file. This file
478       is part of CZMQ, the high-level C binding for 0MQ:
479       http://czmq.zeromq.org. This Source Code Form is subject to the terms
480       of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
481       distributed with this file, You can obtain one at
482       http://mozilla.org/MPL/2.0/. LICENSE included with the czmq
483       distribution.
484

NOTES

486        1. zeromq-dev@lists.zeromq.org
487           mailto:zeromq-dev@lists.zeromq.org
488
489
490
491CZMQ 4.2.1                        07/20/2022                         ZFRAME(3)
Impressum