使用ZeroMQ ZMQ_STREAM作为tcp客户端。为什么我收到额外的信息?

时间:2017-11-29 19:20:24

标签: tcp zeromq

我有一个使用ZeroMQ进行各种操作的应用程序,我也希望将它用作其他外部连接的tcp-client。

目前,如果外部tcp-server发送数据,则客户端接收5字节id,0字节,5字节,然后是实际消息。

如何让ZeroMQ不发送这些内容?

#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;
}

1 个答案:

答案 0 :(得分:1)

步骤1:不要惊慌。

这很容易 - 要么停止使用ZeroMQ,要么开始设计与已发布的ZeroMQ API文档兼容的东西。寻求第三种方式仍然是可能的,但人们可能很容易猜到这样一个fork项目将会完成。

最好让我们开始重新阅读API中的设计规则:

为什么我收到额外信息? ZeroMQ发布的API说:

  

原生模式

     

本机模式用于与TCP对等体通信,并允许异步请求和回复。

     

<强> ZMQ_STREAM

     

类型ZMQ_STREAM的套接字用于在使用tcp://传输时从非ØMQ对等方发送和接收TCP数据。 ZMQ_STREAM套接字可以充当客户端和/或服务器,异步发送和/或接收TCP数据。

     

在接收TCP数据时,ZMQ_STREAM套接字应在将消息部分传递给应用程序之前,将包含发起对等体标识的消息部分添加到消息中。收到的消息在所有连接的对等体中排队等候。

     

发送TCP数据时,ZMQ_STREAM套接字应删除消息的第一部分,并使用它来确定消息应路由到的对等体的身份,并且不可路由的消息应导致{{1} }或EHOSTUNREACH错误。

     

要打开与服务器的连接,请使用 EAGAIN 调用,然后使用 zmq_connect 调用来获取套接字标识。< / p>      

要关闭特定连接,请发送标识帧,然后发送零长度消息(参见示例部分)。

     

建立连接后,应用程序将收到零长度消息。同样,当对等体断开连接(或连接丢失)时,应用程序将收到零长度消息。

     

您必须发送一个标识帧,然后发送一个数据帧。标识帧需要 ZMQ_IDENTITY zmq_getsockopt 标志,但在数据框上会被忽略。

其余的很明显,请遵循用户代码中的API记录行为,并且所有ZeroMQ事物都可以作为魅力。