python - 如何将数据序列化为 C++ zmq 客户端和 Python zmq 服务器之间的通信

标签 python c++ serialization zeromq

更新我的问题

如何在我的 python zmq 服务器中表示到达的消息以显示其内容?

根据这种行为,我是否可以假设 btnState 数据无论如何都会发送到 python 服务器?

上下文:

我正在发送一些数据成员结构 使用 C++ zeromq 客户端进程: ZMQComponent.h 文件

#include <zmq.hpp>
#include <sofa/defaulttype/VecTypes.h>

// To Quat datatype
#include <sofa/defaulttype/Quat.h>
using sofa::defaulttype::Quat;

using std::string;

namespace sofa
{

namespace component
{

namespace controller
{

/* data structure which I want send data to python zmq server */
struct instrumentData
{
  typedef sofa::defaulttype::Vec3d Vec3d;
  Vec3d pos;
  Quat quat;
  int btnState;
  float openInst;
  bool blnDataReady;
};

class ZMQComponent : public sofa::core::behavior::BaseController
{
  public:
    SOFA_CLASS(ZMQComponent, sofa::core::behavior::BaseController);

    ZMQComponent();
    virtual ~ZMQComponent();

    /* Conect to ZMQ external python Server  */
    void setupConnection();

    /* Send some data memeber instrumentData structure to ZMQ external Server  */
    void instrumentDataSend(instrumentData a);

    /* initialize function */
    void init();

};

} // namespace sofa

} // namespace component

} // namespace controller

ZMQComponent.cpp 是:

#include <sofa/core/ObjectFactory.h>
#include <zmq.hpp>
#include <iostream>
#include <string>
#include "ZMQComponent.h"


using namespace std;

namespace sofa
{

namespace component
{

namespace controller
{

/*  ZMQ Internal Client context and socket */
zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REQ);

ZMQComponent::ZMQComponent(){}

void ZMQComponent::setupConnection()
{
    cout << "Connecting to python zeroMQ server ..." << endl;
    socket.connect("tcp://localhost:5555");
}

void ZMQComponent::instrumentDataSend(instrumentData a)
{
    /*  Initialize the data members structure instrumentData */
    a.pos = sofa::defaulttype::Vec3d(1.0f, 1.0f, 1.0f);
    a.quat = defaulttype::Quat(1.0f, 1.0f, 4.0f, 1.0f);
    a.btnState = 5671;
    a.openInst = 1.0f;
    a.blnDataReady = false;

    string s, test, result, d;
    s = to_string(a.btnState);
    test = " is a number";
    result = s + test;

    /*  We send  the btnState data  */
    zmq::message_t request(30);



/*  We ask for the memory address to ge the btnState content and send it. */
    memcpy(request.data(), &result, 30);
    socket.send(request);
}


/*  In the init function we create the objects to setup connection and send data  */
void ZMQComponent::init()
{
    std::cout << "ZeroMQCommunication::init()" << std::endl;
    ZMQComponent z;
    z.setupConnection();

    instrumentData itemp;
    z.instrumentDataSend(itemp);

}

/*  Other code related ....  */
ZMQComponent::~ZMQComponent(){}

// int ZeroMqComponentClass = sofa::core::RegisterObject("This component does nothing.").add<ZeroMqComponent>();
SOFA_DECL_CLASS(ZMQServerComponent)

int ZMQServerComponentClass = sofa::core::RegisterObject("This component create a Socket.").add< ZMQServerComponent >();
} // namespace controller

} // namespace component

} // namespace sofa

然后,接收 btnState int 变量的 python zmq 服务器是:

import time
import zmq

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5555")
print('ZMQ Server listening ... ')

while True:
    #  Wait for next request from client
    message = socket.recv()
    print("Received message from Sofa: {}".format(message))

    #  Do some 'work'
    time.sleep(1)

到达python zmq服务器的输出或消息是result变量的内容(btnState转为string in s content变量+string test 串联) 和 :

的一些符号字符
(cnvss_test) ➜  Python git:(ZMQCommunication) ✗ python server.py
ZMQ Server listening ...
Received message from Sofa: b'\xb0\x1d\x19\xf4\xfd\x7f\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x0045 is a number'

我的 ZMQ python 服务器脚本上的先前输出显示来自 sofa 的字符串 result 已到达服务器,并且它们的内容是可视化的,但是这个字符串或字符符号,它们是产品或开始时在我的 C++ 客户端中定义的 zmq::message_t request(30) 大小的结果。

如果我在请求中分配一个小于 30 的值,例如 zmq::message_t request(10),我服务器的输出是:

Received message from Sofa: b'\x90\x94\xa1\x00\xfc\x7f\x00\x00\x0e\x00'

如果我在请求中分配一个大于 10 的值,例如 zmq::message_t request(20) 我服务器的输出是:

Received message from Sofa: b'\x80$(\xc7\xfc\x7f\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x0045 i

然后,我在服务器端收到的字符串或对象,只要分配给zmq::message_t request变量的长度或大小

根据上面所说,在我的消息中添加这个字符串的ZMQ是否收到了?

根据前面的流程,我的消息到达了我的服务器,那么正确的尝试是什么,像 Protocol Buffer 这样的实体的序列化过程是必要的吗? 我知道使用像 google protocol buffer 这样的东西允许在发送的对象和接收的对象与其真实内容相关方面有一些相关性得到更多控制......

无论如何,如何才能删除到达服务器的消息中添加的字符串或字符符号?

任何支持或指导将不胜感激

最佳答案

您的系统是异构的,这意味着您需要某种与平台/语言无关的序列化。

出于您的目的,最方便使用的可能是 Google Protocol Buffers。这很好地支持 C++ 和 Python。有了这个,您将在模式文件(文件扩展名 .proto)中定义您的消息/数据结构,并使用 protoc 将其编译为 C++ 源代码以及到 Python 源代码。这些为您提供了可以序列化/反序列化到/来自相同线格式的类。序列化/反序列化可以很好地与 ZMQ 消息缓冲区集成。

还有其他的;

  • Apache Avro 是一种可能。
  • 我会避免 XSD 模式;原则上它们很好,但找到真正完成正确和完整工作的代码生成器是困难的/昂贵的。例如,xsd.exe(来自 Microsoft)可以将 XSD 架构编译为 C++ 类(我认为),但会忽略架构中的约束字段(例如 MinInclusive)。
  • ASN1 确实不错,但我还没有找到适合 Python 的实现。有一个用于 python (pyasn) 的 ASN.1 的代码优先实现,但这却忽​​略了拥有 ASN.1 模式的全部要点......

关于python - 如何将数据序列化为 C++ zmq 客户端和 Python zmq 服务器之间的通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48436078/

相关文章:

python - 如果我在字符串中有属性名称,如何从对象获取属性?

python - 如何将字符串转换为属性?

python - 对 python 类属性进行单元测试

c++ - conio.h getch() 的 Linux 等价物

c++ - Boost.Program_options 语法

java - 如何指示 jackson 序列化一个对象内的字段而不是它自己的对象?

python - 如何使用 asksaveasfile 对话框写入 DataFrame 类型的数据

c++ - 重新声明静态 constexpr 数据成员?

javascript - 无法正确序列化 JavaScript 对象

java - 当我尝试从外部文件读取时,为什么 readObject 挂起?