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

C++ 通过TCP套接字发送XDR的好方法,c++,tcpsocket,xdr,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(

我有一些通过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);
XDR;
int i;
xdrrec_create(&ixdr,0,0,重新解释_cast(&ui)和underflow,0);
ixdr.x_op=XDR_解码;

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

问题是xdr_uint32_t正在阻塞

否。XDR函数没有阻塞。一个也没有。阅读来源。阻塞的是
read()
函数

因此,如果我将read和xdr_uint32_t放在同一个线程中,并且在完成整个流的读取之前运行xdr_uint32_t

那没有道理。看看我上面写的。”当XDR库要求您阅读时,您只需阅读。而不是之前

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

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


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

您使用的是什么XDR库?您好,我使用的是Linux,我只是简单地将数据包大小包括在内。当XDR库要求您阅读时,您只需阅读即可。其中一种XDR流类型处理包含长度字的流,但已经超过20年了,我不记得是哪种类型。您是否建议使用xdrrec而不是xdrmem?是的,它是
XDR\u rec
,您可以提供自己的读写函数。