簡體   English   中英

如何將數據序列化為C ++ zmq客戶端和Python zmq Server之間的通信

[英]How to can I serialize data to Communication between C++ zmq client and Python zmq Server

更新我的問題

如何在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轉換為s中的字符串內容變量+串聯的字符串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服務器腳本上的先前輸出顯示,沙發的字符串result已到達服務器,並且其內容也已可視化,但是這些字符串或字符符號也是zmq::message_t request(30)大小的乘積或結果一開始在我的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是誰在收到的消息中添加了這些字符串嗎?

根據先前的過程,我的消息到達了我的服務器,然后正確嘗試使用諸如協議緩沖區之類的某些實體進行的序列化過程是必要的嗎? 我了解使用類似google協議緩沖區之類的東西,可以相對於發送的對象和接收到的對象的真實內容,更好地控制某些關聯...

無論如何,如何刪除到達服務器的消息中添加的字符串或字符符號?

任何支持或方向將不勝感激

您的系統是異構的,這意味着您需要某種與平台/語言無關的序列化。

為了您的目的,最方便使用的可能是Google Protocol Buffers 這很好地支持C ++和Python。 有了這個,你會定義一個模式文件(文件擴展名的消息/數據結構.proto ),並使用protoc來編譯到兩個C ++源代碼,並以Python源代碼。 這些為您提供了可以在同一線格式中進行序列化/反序列化的類。 序列化/反序列化可以很好地與ZMQ消息緩沖區集成。

還有其他

  • Apache Avro是有可能的。
  • 我會避免使用XSD模式。 從原則上講,它們很好,但是要找到能夠真正完成適當工作的代碼生成器是困難的/昂貴的。 例如, xsd.exe (來自Microsoft)可以將XSD架構編譯為C ++類(我認為),但是忽略架構(ed MinInclusive )中的約束字段。
  • ASN1確實不錯,但是我還沒有找到適合Python的實現。 有一個針對python(pyasn)的ASN.1的代碼優先實現,但是卻錯過了擁有ASN.1模式的整個要點...

我在c + +中使用類似的zmq實現,並且具有沙發框架(與autor插件有關)。

我從zmq C ++向python zmq發送數據沒有任何問題。

這是我用python編寫的zmq服務器的概述:

import zmq

context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.setsockopt(zmq.SUBSCRIBE, "")

print "Collecting data from c++ ..."
socket.connect ("tcp://127.0.0.1:6000")

while True:
    print socket.recv()

這里是結果的概述:

douaille@douaille:~/Documents/zmq$ python zmqClient.py 
Collecting data from c++ ...
/colorLight string:'1 1 1 1' 
/colorLight string:'1 1 1 1' 
/colorLight string:'1 1 1 1' 
/colorLight string:'1 1 1 1' 
/colorLight string:'1 1 1 1' 
/colorLight string:'1 1 1 1' 

我正在使用zmq作為發布者,但是它並不能更改您需要的任何內容。 加上請求客戶端的實現幾乎相同。 看起來您正在打印請求而不是消息

您可以在此處找到c ++發送器部分的實現: https : //github.com/SofaDefrost/sofa/blob/sofaCommunication/applications/plugins/Communication/components/serverCommunicationZMQ.inl

編輯:

這是使用zmq request的示例:

import zmq

context = zmq.Context()
socket = context.socket(zmq.REQ)

print("Collecting data from c++ using REQ ...")
socket.connect("tcp://localhost:6000")

while True:
    print("Sending request")
    socket.send(b"Hello")
    message = socket.recv()
    print("Received reply : %s" % message)

結果:

douaille@douaille:~/Documents/zmq$ python zmqClient.py 
Collecting data from c++ using REQ ...
Sending request
Received reply : /colorLight string:'1 1 1 1' 
Sending request
Received reply : /colorLight string:'1 1 1 1' 
Sending request
Received reply : /colorLight string:'1 1 1 1' 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM