2016-03-15 35 views
4

嗨,我想在poco中編寫一個TCP連接。客戶端發送的分組與該字段:如何複製Poco C++中的緩衝區字節塊?

packetSize : int date : int ID : int

所以第4個字節中包含的分組大小。在接收端我有這樣的代碼:

int packetSize = 0; 
char *bufferHeader = new char[4]; 

// receive 4 bytes that contains packetsize here 
socket().receiveBytes(bufferHeader, sizeof(bufferHeader), MSG_WAITALL); 

Poco::MemoryInputStream *inStreamHeader = new Poco::MemoryInputStream(bufferHeader, sizeof(bufferHeader)); 
Poco::BinaryReader *BinaryReaderHeader = new Poco::BinaryReader(*inStreamHeader); 

(*BinaryReaderHeader) >> packetSize; // now we have the full packet size 

現在我想所有剩餘的進入數據的字節存儲到一個數組,未來的二進制閱讀:

int ID = 0; 
int date = 0; 
int availableBytes = 0; 
int readedBytes = 0; 
char *body = new char[packetSize - 4]; 

do 
{ 
    char *bytes = new char[packetSize - 4]; 

    availableBytes = socket().receiveBytes(bytes, sizeof(bytes), MSG_WAITALL); 

    if (availableBytes == 0) 
     break; 

    memcpy(body + readedBytes, bytes, availableBytes); 

    readedBytes += availableBytes; 

} while (availableBytes > 0); 

Poco::MemoryInputStream *inStream = new Poco::MemoryInputStream(body, sizeof(body)); 
Poco::BinaryReader *BinaryReader = new Poco::BinaryReader(*inStream); 

(*BinaryReader) >> date; 
(*BinaryReader) >> ID; 

cout << "date :" << date << endl; 
cout << "ID :" << ID << endl; 

問題是身體的字節塊沒有存儲剩餘的字節,它總是隻有前4個字節(日期)。所以在輸出日期是正確的,但ID不是預期的。我試圖在沒有塊複製的情況下對其進行流式處理,並且手動接收沒有循環的每個域,這很好,並且有預期的數據。但是當我嘗試將傳入字節存儲到一個數組中,然後將該數組傳遞給內存流以讀取它時,我只有第一個塊正確且預期!

我真的需要將所有傳入的字節存儲到一個數組中,然後讀取整個數組,我該如何更改我的代碼?

非常感謝

回答

1

我在代碼中看到兩個錯誤。或者更準確地說,你犯了兩次錯誤。 您混淆了sizeofchar[]sizeofchar *;第一個是數組中的字符數,第二個是指針的大小:通常爲4或8個字節,具體取決於內存模型。

所以,當你寫

availableBytes = socket().receiveBytes(bytes, sizeof(bytes), MSG_WAITALL); 

你所要求的4(我想)字節。這並不嚴重,因爲您繼續詢問其他字節,直到消息完成。

真正的問題是下面的指令

Poco::MemoryInputStream *inStream = new Poco::MemoryInputStream(body, sizeof(body)); 

,你在inStream

只傳輸sizeof(char *)字節您應該取代sizeof(body)sizeof(bytes)packetSize - 4

P.S:對不起,我的英語不好

編輯:我已經看到了另一個錯誤。在此指令中

char *bytes = new char[packetSize - 4]; 

您分配packetSize - 4字符。該存儲器在永不刪除和分配在do ... while()週期中。

您可以在週期之外分配bytes(與body一起打印)。

編輯2016.03。17

提出的解決方案(小心:非測試)

size_t toRead = packetSize - 4U; 
size_t totRead = 0U; 
size_t nowRead; 

char * body = new char[toRead]; 

do 
{ 
    nowRead += socket().receiveBytes(body+totRead, toRead-totRead, 
       MSG_WAITALL); 

    if (0 == nowRead) 
    throw std::runtime_error("shutdown from receiveBytes()"); 

    totRead += nowRead; 

} while (totRead < toRead); 

Poco::MemoryInputStream *inStream = new Poco::MemoryInputStream(body, 
              toRead); 

delete[] body; 

body = NULL; 
+0

感謝UR響應。是的,我對此感到困惑,畢竟當我改變char *爲char []時,我正在獲取完整的數據包。但實際上,當我想爲我的緩衝區考慮packetSize時,我無法調整Char []的大小,實際上C++並不接受數組的大小,它需要常量值,但它接受爲:'char * buffer = new char [packetSize ]',當我考慮char *時,我每次只得到4個字節,而不是完整的數據包。我怎麼解決這個問題? –

+0

@AmirHasanHesam:我認爲你應該避免使用'sizeof()';你有期望的字節數:使用它。而且你只能使用一個緩衝區。我將編輯我的答案以顯示可能的解決方案。 – max66

+0

感謝您的回覆,這是我需要的代碼。 –