4

I have an application that uses ZeroMQ for various things and I want to also use it as a tcp-client for other external connections.

Currently if the external tcp-server sends data, the client receives 5 byte id, 0 bytes, 5 bytes, and then actual message.

How do I get ZeroMQ not to send this stuff?

#include <iostream>
#include <string>
#include <zmq.h>
#include <cstring>
#include <assert.h>
#include <chrono>
#include <thread>


int main()
{
  void *mpSocketContext = zmq_ctx_new();

  /* Create ZMQ_STREAM socket */
  void *mpSerialSocket = zmq_socket(mpSocketContext, ZMQ_STREAM);
  void *mpSocket = mpSerialSocket;
  bool aeBlocking = true;

  std::string asAddress = "127.0.0.1:1236";
  asAddress  = "tcp://" + asAddress;

  std::cout << "tcSerialServerPort::tcSerialServerPort: connecting to " << asAddress << std::endl;

  int rc = zmq_connect(mpSerialSocket, asAddress.c_str());
  if (rc != 0)
    std::cout << "ZMQ ERROR: zmq_connect " <<  zmq_strerror(zmq_errno()) << std::endl;

  uint8_t id [256];
  size_t id_size = 256;
  rc = zmq_getsockopt (mpSerialSocket, ZMQ_IDENTITY, id, &id_size);
  assert(rc == 0);

  while(true)
  {
  zmq_msg_t msg;
  zmq_msg_init(&msg);
  size_t lnBytesReceived = 0;
  std::string lsStr;

  lnBytesReceived = zmq_recvmsg(mpSocket, &msg, aeBlocking ? 0 : ZMQ_DONTWAIT);

  lsStr = std::string(static_cast<const char*>(zmq_msg_data(&msg)),
      zmq_msg_size(&msg));


  std::cout << "Received Bytes=" << lsStr.size() << " Data=" << lsStr << std::endl;

  zmq_msg_close(&msg);

  std::this_thread::sleep_for(std::chrono::seconds(1));
  }


  zmq_close(mpSerialSocket);
  zmq_ctx_destroy(mpSocketContext);

  return 0;
}
user3666197
  • 1
  • 6
  • 50
  • 92
CptanPanic
  • 828
  • 2
  • 10
  • 19

1 Answers1

3

Step #1: Don't panic.

It is very easy - either stop using ZeroMQ, or start to design things compatible with the published ZeroMQ API documentation. Seeking a third way is still possible, but one may easily guess what such a fork-project will finish in.

Best let's start re-reading the design rules from the API:

"Why am I receiving extra info?" The ZeroMQ published API says:

Native pattern

The native pattern is used for communicating with TCP peers and allows asynchronous requests and replies in either direction.

ZMQ_STREAM

A socket of type ZMQ_STREAM is used to send and receive TCP data from a non-ØMQ peer, when using the tcp:// transport. A ZMQ_STREAM socket can act as client and/or server, sending and/or receiving TCP data asynchronously.

When receiving TCP data, a ZMQ_STREAM socket shall prepend a message part 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.

When sending TCP data, a ZMQ_STREAM socket shall remove the first part of the message and use it to determine the identity of the peer the message shall be routed to, and unroutable messages shall cause an EHOSTUNREACH or EAGAIN error.

To open a connection to a server, use the zmq_connect call, and then fetch the socket identity using the ZMQ_IDENTITY zmq_getsockopt call.

To close a specific connection, send the identity frame followed by a zero-length message (see EXAMPLE section).

When a connection is made, a zero-length message will be received by the application. Similarly, when the peer disconnects (or the connection is lost), a zero-length message will be received by the application.

You must send one identity frame followed by one data frame. The ZMQ_SNDMORE flag is required for identity frames but is ignored on data frames.

The rest is obvious, follow the API documented behaviour in the user-code and all the ZeroMQ things work as charm.

user3666197
  • 1
  • 6
  • 50
  • 92
  • 1
    Yes I have already seen this portion of the man page. So I am to understand that the first 2 receives I get are the identity, and the zero length message indicating a connection. Then the real data comes in so I get a 5 byte identity and then the data. – CptanPanic Nov 30 '17 at 01:57
  • Sure, implement the "state"-management automation, as was documented in API. **Beware:** ZeroMQ Socket()-instance is **not** a TCP-socket-as-you-know-it. Best read about the main concept differences in **[ ZeroMQ hierarchy in less than a five seconds ]** Section in >>> https://stackoverflow.com/a/46620571/ **Once** you get the view, there could be more than 1:1 relation for 1x(anAccess-POINT):Nx(aTransportClassLINK)...leading to 1xAccessPoint(ZMQ_STREAM):10xTcpLINK([A,B,C,..,J]), each going to a different counterparty, the ZMQ_IDENTITY & all the circus will start to make better sense for you. – user3666197 Nov 30 '17 at 10:48