2

我正在尝试通过 ZMQ 通过网络发送一个相当大的 Flatbuffers 对象,然后使用 C++ 读取它。访问对象时,我得到了我不知道如何解决的未处理异常。即使这个最小的例子也失败了:

flatbuffers 架构:

namespace flatbuffer;
table TestBuf {
  testStatus:bool;
  testNumber:double;
  testInt:int;
}
root_type TestBuf;

使用 REP 套接字的 main.cpp:

int main() {
    zmq::context_t context(1);
    zmq::socket_t socket(context, ZMQ_REP);
    socket.bind("tcp://*:5555");

    std::cout << "Listening for requests." << std::endl;
    std::cout << "-----" << std::endl;

    double count = 0;
    while (1) {
        zmq::message_t request;
        socket.recv(&request);

        // Read incoming data
        auto reqmsg = flatbuffer::GetTestBuf(&request);
        std::cout << "Received: " << reqmsg << std::endl;

        flatbuffers::FlatBufferBuilder fbb;
        flatbuffer::TestBufBuilder builder(fbb);

        count++;
        builder.add_testNumber(count);      
        std::cout << "Sending " << count << std::endl;

        auto response = builder.Finish();
        fbb.Finish(response);

        // Send the flatbuffer
        int buffersize = fbb.GetSize();
        zmq::message_t message(buffersize);
        memcpy((void *)message.data(), fbb.GetBufferPointer(), buffersize);
        socket.send(message);
    }
    return 0;
}

使用 REQ 套接字的 main.cpp:

int main() {
    // Prepare ZMQ context and socket
    zmq::context_t context(1);
    zmq::socket_t socket(context, ZMQ_REQ);
    std::cout << "Sending out data requests." << std::endl;
    socket.connect("tcp://localhost:5555");

    double count = 0;
    while (1) {
        // Formulate response
        flatbuffers::FlatBufferBuilder fbb;
        flatbuffer::TestBufBuilder builder(fbb);

        count++;
        builder.add_testNumber(count);
        auto response = builder.Finish();
        fbb.Finish(response);

        // Send the flatbuffer
        std::cout << "Sending. " << count << ". ";
        int buffersize = fbb.GetSize();
        zmq::message_t message(buffersize);
        memcpy((void *)message.data(), fbb.GetBufferPointer(), buffersize);
        socket.send(message);
        std::cout << "Sent. ";

        // Receive reply
        zmq::message_t reply;
        socket.recv(&reply);

        // Read the data
        auto inmsg = flatbuffer::GetTestBuf(&reply);
        std::cout << " Received reply: " << inmsg << std::endl;

        //auto num = inmsg->testNumber();
        //std::cout << num << " test number.";
    }
    return 0;
}

此代码运行良好并显示(我认为)每个程序正在接收的原始缓冲区。奇怪的是,它并没有改变,尽管消息的内容应该是。如果我取消注释最后两行并尝试访问 inmsg->testNumber(),我会收到以下错误消息:

Unhandled exception at 0x000000013F373C53 in KUKAREQ.exe: 0xC0000005: Access violation reading location 0x00000000004B35D8.

我之前已经通过 ZMQ 成功发送了 Flatbuffers 对象,但我还没有在 C++ 中读取它们。我很确定我遵循了Flatbuffers 教程,但显然出了点问题。指针?缓冲区大小?无论哪种方式,我都会感谢帮助。


编辑:为了澄清我对已接受答案的评论,违规行是:

auto inmsg = flatbuffer::GetTestBuf(&reply);

它必须更改为:

auto inmsg = flatbuffer::GetTestBuf(reply.data());

阅读此问题的人也可能有兴趣知道我后来遇到了一个错误,该错误是在未按正确顺序调用 FlatBufferBuilder 函数时发生的。显然,Flatbuffers 对象的构建顺序很重要。我花了一段时间才找到那个——新手要小心。

4

1 回答 1

2

不熟悉 ZeroMQ,但这flatbuffer::GetTestBuf(&request)看起来有问题..您需要传递缓冲区,而不是消息结构。可能request.data()或类似的效果更好。

一般来说,如果它在 FlatBuffers 中崩溃,您应该使用验证器来验证您传递给 FlatBuffers 的缓冲区。如果失败,则意味着您没有将合法数据传递给 FlatBuffers,就像这里的情况一样。

此外,您可能想检查 ZeroMQ 是否可以在不复制的情况下发送缓冲区,这会更快。

于 2016-03-13T20:49:39.203 回答