2016-03-15 132 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