1

我有一些通过 TCP 套接字发送的 XDR 数据包。这是我的代码片段:

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!");
}

其中数据包被序列化如下:

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.");
        }
    }

....

}

作为第一个测试,我假设最大数据包大小为 2000,并且我总是从另一侧读取 2000。作为第一次测试,这项工作很好,但我希望能够在不需要时发送和接收更少的信息。此外,我不想重新编译客户端,以防我增加服务器上的数据包大小。

我想知道是否有适当的方法来发送和接收此流,而不必自己预先设置数据包大小。如果我必须自己添加这个,有没有办法轻松获得 xdr 大小?

干杯,

补充: 我尝试使用 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);

如果我给它一个正确的 10 uint32 缓冲区,一切都很好。现在我试图在我的缓冲区末尾剪切一些字节,我期待或者xdrrec_eofxdrrec_skiprecord我一个错误。这就是我想用它来检测我还没有收到所有数据。取而代之的是,两者都成功返回并xdr_uint32_t阻止代码执行。所以我现在真正想念的是一种在开始解码之前检测到我已经收到完整数据包的方法xdr_uint32_t。有什么建议吗?

4

1 回答 1

1

数据包大小无关紧要。当 XDR 库要求您阅读时,您只需阅读即可。XDRxdr_rec流类型处理其中包含长度字的流。您所要做的就是为它提供您自己的读写功能。我这样做已经 22 年了,但这并不难。我不明白为什么您认为您需要“在开始解码之前接收完整的数据包”。你没有。将根据需要经常xdr_rec调用您的函数。read()

问题是 xdr_uint32_t 阻塞

不会。XDR 功能不会阻塞。没有之一。阅读源代码。它是read()阻塞的功能。

所以如果我在同一个线程中有读取和 xdr_uint32_t 并且我在完成读取整个流之前运行 xdr_uint32_t

那没有意义。阅读我上面写的。“当 XDR 库要求您阅读时,您只需阅读即可。” 不是以前。

这可能会阻止应用程序。所以可能我需要在 2 个单独的线程中读取套接字和解码。

不,你似乎不明白它是如何xdr_rec工作的。您创建一个xdr_rec对象并为其提供一个读取回调函数和一个写入回调函数。从那里您只需调用您喜欢的任何 XDR 例程,它们会根据需要调用读或写回调。你根本不给他们打电话。不需要先“阅读整个流”。

您应该在一个线程中完成所有这些操作。

于 2016-03-17T10:02:59.153 回答