简体   繁体   English

通过 TCP 套接字发送 XDR 的好方法

[英]Good way for sending XDR over TCP Socket

I Have some XDR data packets which are sent over a TCP socket.我有一些通过 TCP 套接字发送的 XDR 数据包。 Here a snippet of my code:这是我的代码片段:

const size_t BUFFER_LENGTH = 2000;
XDR xdr;
char *buffer = new char[BUFFER_LENGTH];
xdrmem_create(&xdr, buffer, BUFFER_LENGTH, XDR_ENCODE);

const std::string requestId = request->getPacket()->getRequestId();
MyPacket responcePacket(requestId, status,message);
responcePacket.serialize(&xdr);

unsigned int byteSent = write(*socketDescriptor_, buffer, BUFFER_LENGTH);
delete buffer;
if(byteSent!=BUFFER_LENGTH)
{
    throw Exception("Error during write!");
}

where the packet is serialized as follow:其中数据包序列化如下:

class MyPacket:

    void MyPacket::serialize(XDR* xdr)
    {
        // Convert Enum to int
        int _messageType = (int) messageType_;
        uint32_t _status = (uint32_t) status_;

        //Copy all strings to c_string
        char *_requestId = new char[requestId_.length() + 1];
        std::strcpy(_requestId,requestId_.c_str());

        char *_message = new char[message_.length() + 1];
        std::strcpy(_message,message_.c_str());

        bool status = xdr_int(xdr, &_messageType) &&
                    xdr_string(xdr, &_requestId, REQUESTID_LENGTH_) &&
                    xdr_u_int(xdr, &_status ) &&
                    xdr_string(xdr, &_message, MESSAGE_LENGTH_);

        delete _requestId;
        delete _message;

        if(!status)
        {
            throw new Exception("Error while serializing MyPacket.");
        }
    }

....

}

As a first test I am assuming the maximum packet size to be 2000 and I am always reading 2000 from the other side.作为第一个测试,我假设最大数据包大小为 2000,并且我总是从另一侧读取 2000。 As a first test this work fine but I would like to be able to send and receive less information when not required.作为第一次测试,这项工作很好,但我希望能够在不需要时发送和接收更少的信息。 Furthermore i do not want to have to recompile the client in case i increase the packet size on my server.此外,如果我增加服务器上的数据包大小,我不想重新编译客户端。

I would like to know if there is a proper way to send and receive this stream without having to prepend the packet size myself.我想知道是否有一种正确的方法来发送和接收这个流,而不必自己预先考虑数据包大小。 And In case I have to prepend this myself is there a way to easily get the xdr size?如果我必须自己加上这个,有没有办法轻松获得 xdr 大小?

Cheers,干杯,

ADDITION: I tried using a xdr_rec buffer as follows:添加:我尝试使用 xdr_rec 缓冲区,如下所示:

XDR ixdr;
int i;
xdrrec_create (&ixdr,0,0,reinterpret_cast<char*> (&ui),&underflow,0);
ixdr.x_op = XDR_DECODE;

cout << "xdrrec_eof: " << xdrrec_eof (&ixdr) <<endl;
cout << "xdrrec_skiprecord: " << xdrrec_skiprecord (&ixdr) <<endl;

for(j=0;j<10;j++){
    xdr_uint32_t (&ixdr, &i);
    cerr << "i: " << i << endl;
}xdr_destroy (&ixdr);

If i feed to it a correct buffer with 10 uint32 all works great.如果我用 10 uint32 给它提供一个正确的缓冲区,一切都很好。 Now I tried to cut some bytes at the end of my buffer and I was expecting either xdrrec_eof or xdrrec_skiprecord to give me an error.现在我试图在缓冲区的末尾削减一些字节,我期待xdrrec_eofxdrrec_skiprecord给我一个错误。 This is what I wanted to use to detect that I did not have received all the data yet.这就是我想用来检测我还没有收到所有数据的东西。 What happens instead is that both return with success and the xdr_uint32_t blocks the code execution.相反发生的情况是,两者都成功返回并且xdr_uint32_t阻止了代码执行。 So what i now really still miss is a way to detect that i had received the full packet before start decoding it with xdr_uint32_t .所以我现在真正仍然想念的是一种在开始使用xdr_uint32_t解码之前检测我已经收到完整数据包的xdr_uint32_t Any suggestion?有什么建议吗?

The packet size is irrelevant.数据包大小无关紧要。 You just have to read when the XDR library asks you to read.您只需要在 XDR 库要求您阅读时阅读即可。 The XDR xdr_rec stream type deals with streams with length words in them. XDR xdr_rec流类型处理其中包含长度字的流。 All you have to do is supply it with your own read and write functions.您所要做的就是为它提供您自己的读写功能。 It's 22 years since I did this but it wasn't difficult.我做这件事已经 22 年了,但这并不困难。 I don't understand why you think you need to 'receive a full packet before start[ing] decoding'.我不明白为什么你认为你需要“在开始[ing]解码之前接收一个完整的数据包”。 You don't.你没有。 xdr_rec will call your read() function as often as it needs to. xdr_rec将根据需要经常调用您的read()函数。

The problem is that xdr_uint32_t is blocking问题是 xdr_uint32_t 正在阻塞

No. XDR functions are not blocking.不会。XDR 功能不会阻塞。 Not one of them.不是其中之一。 Read the source.阅读源码。 It is the read() function that blocks.阻塞的是read()函数。

so if i have the read and the xdr_uint32_t in the same thread and i run xdr_uint32_t before having finished reading the whole stream所以如果我在同一个线程中读取和 xdr_uint32_t 并且我在完成读取整个流之前运行 xdr_uint32_t

That doesn't make sense.那没有意义。 Read what I wrote above.阅读我上面写的内容。 'You just have to read when the XDR library asks you to read.' “你只需要在 XDR 库要求你阅读时阅读。” Not before.以前不是。

this risks to block the application.这有阻止应用程序的风险。 So probably i need to have the socket reading and the decoding in 2 separate threads.所以可能我需要在 2 个单独的线程中进行套接字读取和解码。

No. You don't seem to understand how xdr_rec works.不。您似乎不了解xdr_rec工作原理。 You create an xdr_rec object and supply it with a read callback function and a write callback function.您创建一个xdr_rec对象并为其提供读取回调函数和写入回调函数。 From there on you just call whatever XDR routines you like, and they call the read or write callbacks as appropriate.从那时起,您只需调用您喜欢的任何 XDR 例程,它们会根据需要调用读取或写入回调。 You don't call them at all.你根本不打电话给他们。 There is no requirement to 'read the whole stream' first.不需要先“阅读整个流”。

You should do all this in a single thread.你应该在一个线程中完成所有这些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM