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

时间:2016-03-15 07:52:41

标签: c++ tcpsocket xdr

我有一些通过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开始解码之前收到了完整的数据包。有什么建议吗?

1 个答案:

答案 0 :(得分:1)

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

  

问题是xdr_uint32_t正在阻止

没有。 XDR功能未阻止。不是其中之一。阅读来源。阻止read()函数。

  

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

这没有意义。阅读我上面写的内容。 &#39;您只需在XDR库要求您阅读时阅读。&#39;不是之前。

  

这会阻碍申请。所以我可能需要在2个独立的线程中进行套接字读取和解码。

没有。您似乎并不了解xdr_rec的工作原理。您创建一个xdr_rec对象并为其提供读回调函数和写回调函数。从那里开始,您只需调用您喜欢的任何XDR例程,并且他们根据需要调用读取或写入回调。你根本不打电话给他们。没有要求阅读整个流&#39;第一

你应该在一个线程中完成所有这些。

相关问题