[英]Good way for sending XDR over TCP Socket
我有一些通过 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_eof
或xdrrec_skiprecord
给我一个错误。 这就是我想用来检测我还没有收到所有数据的东西。 相反发生的情况是,两者都成功返回并且xdr_uint32_t
阻止了代码执行。 所以我现在真正仍然想念的是一种在开始使用xdr_uint32_t
解码之前检测我已经收到完整数据包的xdr_uint32_t
。 有什么建议吗?
数据包大小无关紧要。 您只需要在 XDR 库要求您阅读时阅读即可。 XDR xdr_rec
流类型处理其中包含长度字的流。 您所要做的就是为它提供您自己的读写功能。 我做这件事已经 22 年了,但这并不困难。 我不明白为什么你认为你需要“在开始[ing]解码之前接收一个完整的数据包”。 你没有。 xdr_rec
将根据需要经常调用您的read()
函数。
问题是 xdr_uint32_t 正在阻塞
不会。XDR 功能不会阻塞。 不是其中之一。 阅读源码。 阻塞的是read()
函数。
所以如果我在同一个线程中读取和 xdr_uint32_t 并且我在完成读取整个流之前运行 xdr_uint32_t
那没有意义。 阅读我上面写的内容。 “你只需要在 XDR 库要求你阅读时阅读。” 以前不是。
这有阻止应用程序的风险。 所以可能我需要在 2 个单独的线程中进行套接字读取和解码。
不。您似乎不了解xdr_rec
工作原理。 您创建一个xdr_rec
对象并为其提供读取回调函数和写入回调函数。 从那时起,您只需调用您喜欢的任何 XDR 例程,它们会根据需要调用读取或写入回调。 你根本不打电话给他们。 不需要先“阅读整个流”。
你应该在一个线程中完成所有这些。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.