I Have some XDR data packets which are sent over a TCP socket. 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. 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?
Cheers,
ADDITION: I tried using a xdr_rec buffer as follows:
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.
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. 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. 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
. Any suggestion?