2016-03-15 125 views
1

我有一些通过TCP套接字发送的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进行解码。任何建议?

+0

你在使用什么XDR库? –

+0

嗨,我在Linux上,我只是包括 Stefano

+1

数据包大小是无关紧要的。当XDR库要求您阅读时,您只需阅读。其中一种XDR流类型处理带有长度单词的流,但已经有20多年了,我不记得是哪一种。 – EJP

回答

1

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

的问题是,xdr_uint32_t阻止

号XDR功能不阻塞。不是其中之一。阅读来源。这是read()功能阻止。

所以,如果我有读取和在同一个线程的xdr_uint32_t,我已经看完了整个流

这没有任何意义之前运行xdr_uint32_t。阅读我上面写的内容。 “当XDR图书馆要求你阅读时,你只需要阅读。”之前没有。

此风险阻止应用程序。所以可能我需要在2个独立的线程中有套接字读取和解码。

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

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

+0

非常感谢。现在一切正常! – Stefano

相关问题