Skip to content

Instantly share code, notes, and snippets.

@claws
Created October 30, 2013 12:07
Show Gist options
  • Save claws/7231548 to your computer and use it in GitHub Desktop.
Save claws/7231548 to your computer and use it in GitHub Desktop.
ZMQ can communicate with non-ZMQ TCP peers using the ZMQ_STREAM socket type. This is a silly example that uses the CZMQ library to create a non-ZMTP TCP server and a non-ZMTP TCP client. It was created to investigate how one might make use of the ZMQ_STREAM socket type.
//
// A minimal TCP client using the ZMQ API. This demonstrates a
// useful mechanism for bridging a ZMQ based system out to other
// TCP based systems.
//
#include "czmq.h"
int main (void)
{
zctx_t *ctx = zctx_new();
void *sock = zsocket_new(ctx, ZMQ_STREAM);
int rc = zsocket_connect(sock, "tcp://127.0.0.1:5555");
if (rc != 0)
printf ("%s", zmq_strerror(zmq_errno()));
assert(rc == 0);
// Retrieve the socket identity. This is important in this
// particular scenario because when sending data using a
// 'ZMQ_STREAM' socket the implementation uses the first
// frame as the *identity* to route the message to. The ZMQ
// implementation strips off this first frame before sending
// the data to the endpoint.
//char *identity = zsocket_identity (sock);
// Must currently resort to the libzmq low-level lib to obtain
// raw identity information because CZMQ is returning the binary
// identity data as a char* and often there is 0 in the data which
// prematurely terminates the char* data.
uint8_t id [256];
size_t id_size = 256;
rc = zmq_getsockopt (sock, ZMQ_IDENTITY, id, &id_size);
assert (rc == 0);
zframe_t *frame;
while (!zctx_interrupted) {
zmsg_t *msg = zmsg_new ();
// Supply ZMQ with the identity to route the message to.
zmsg_addmem (msg, id, id_size);
// add message data.
zmsg_addstr (msg, "Hello");
zmsg_send(&msg, sock);
// When receiving TCP data, a 'ZMQ_STREAM' socket shall
// prepend a frame containing the *identity* of the
// originating peer to the message before passing it to
// the application. Messages received are fair-queued from
// among all connected peers.
//
// So in a multi-connection environment our simple
// assumption that we will receive a reply from the
// endpoint we just sent a message to is naive but will
// suffice for this simple test.
// Read off the *identity* first
frame = zframe_recv (sock);
if (!frame)
break; // interrupted
zframe_destroy (&frame);
// Now read off the message.
char *response = zstr_recv (sock);
printf ("Response: %s\n", response);
free (response);
// crude delay between consequtive requests
zclock_sleep (2000);
}
zctx_destroy (&ctx);
return 0;
}
//
// Minimal TCP server using 0MQ
//
#include "czmq.h"
int main (void)
{
zctx_t *ctx = zctx_new();
void *sock = zsocket_new (ctx, ZMQ_STREAM);
int rc = zsocket_bind (sock, "tcp://*:5555");
assert (rc != -1);
while (!zctx_interrupted) {
// Get connection client identity so we can instruct
// router socket which client to send the response to.
zframe_t *frame = zframe_recv(sock);
if (!frame)
break; // Ctrl-C interrupt
// Read the message
char *request = zstr_recv (sock);
printf ("Received: %s\n", request);
free (request);
// Send response
zframe_send (&frame, sock, ZFRAME_MORE + ZFRAME_REUSE);
zstr_send (sock, "World!");
}
zctx_destroy (&ctx);
return 0;
}
@webandbusiness
Copy link

Very good

@eugenecoetzee67
Copy link

I find the wording "non-ZMTP TCP client" very misleading when you still need to send the ZMQ frame containing the identity. The server doesn't work for example with a netcat client or telnet client that simply sends the text or binary stream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment