2010-04-28 162 views
1

我目前正在研究一個類來創建和讀出通過網絡發送的數據包,到目前爲止我已經使用16位和8位整數(很好的無符號,但仍然)。添加一個字符串或字符數組到一個字節向量

現在的問題是我已經嘗試了很多方法來複制它,但不知何故_buffer得到了損壞,它segfaulted,或結果是錯誤的。

我會很感激,如果有人能給我一個工作的例子。

我現在的代碼可以在下面看到。

感謝,Xeross

主要

#include <iostream> 
#include <stdio.h> 
#include "Packet.h" 

using namespace std; 

int main(int argc, char** argv) 
{ 
    cout << "#################################" << endl; 
    cout << "#  Internal Use Only  #" << endl; 
    cout << "#  Codename PACKETSTORM  #" << endl; 
    cout << "#################################" << endl; 
    cout << endl; 

    Packet packet = Packet(); 
    packet.SetOpcode(0x1f4d); 

    cout << "Current opcode is: " << packet.GetOpcode() << endl << endl; 

    packet.add(uint8_t(5)) 
      .add(uint16_t(4000)) 
      .add(uint8_t(5)); 

    for(uint8_t i=0; i<10;i++) 
     printf("Byte %u = %x\n", i, packet._buffer[i]); 

    printf("\nReading them out: \n1 = %u\n2 = %u\n3 = %u\n4 = %s", 
     packet.readUint8(), 
     packet.readUint16(), 
     packet.readUint8()); 

    return 0; 
} 

Packet.h

#ifndef _PACKET_H_ 
#define _PACKET_H_ 

#include <iostream> 
#include <vector> 

#include <stdio.h> 
#include <stdint.h> 
#include <string.h> 

using namespace std; 

class Packet 
{ 
    public: 
     Packet() : m_opcode(0), _buffer(0), _wpos(0), _rpos(0) {} 
     Packet(uint16_t opcode) : m_opcode(opcode), _buffer(0), _wpos(0), _rpos(0) {} 

     uint16_t GetOpcode() { return m_opcode; } 
     void SetOpcode(uint16_t opcode) { m_opcode = opcode; } 

     Packet& add(uint8_t value) 
     { 
      if(_buffer.size() < _wpos + 1) 
       _buffer.resize(_wpos + 1); 

      memcpy(&_buffer[_wpos], &value, 1); 
      _wpos += 1; 

      return *this; 
     } 
     Packet& add(uint16_t value) 
     { 
      if(_buffer.size() < _wpos + 2) 
       _buffer.resize(_wpos + 2); 

      memcpy(&_buffer[_wpos], &value, 2); 
      _wpos += 2; 

      return *this; 
     } 

     uint8_t readUint8() 
     { 
      uint8_t result = _buffer[_rpos]; 
      _rpos += sizeof(uint8_t); 
      return result; 
     } 
     uint16_t readUint16() 
     { 
      uint16_t result; 
      memcpy(&result, &_buffer[_rpos], sizeof(uint16_t)); 

      _rpos += sizeof(uint16_t); 
      return result; 

     } 

     uint16_t m_opcode; 
     std::vector<uint8_t> _buffer; 
    protected: 

     size_t _wpos; // Write position 
     size_t _rpos; // Read position 
}; 

#endif // _PACKET_H_ 
+1

你的問題表明追加一個字符串或字符數組的問題,但我沒有看到試圖做到這一點的代碼。 – 2010-04-28 12:21:29

+0

我刪除了添加字符串或字符數組的代碼,並希望有人向我展示應該如何完成。否則,我可以在閱讀和書寫時列出5次嘗試 – 2010-04-28 12:22:30

+2

不要混合使用printf和cout。改爲使用cout。 另外stdio.h和它的喜歡被棄用。例如,使用。 對於每個C頭文件,只需在其之前鍵入c併除去.h – 2010-04-28 12:25:49

回答

5

由於您使用的標準::矢量你的緩衝區,你可能也讓它保持跟蹤寫入位置本身,避免不得不手動調整它的大小。您也可以通過避免使用函數模板寫的附加功能的多個重載:

template <class T> 
Packet& add(T value) { 
    std::copy((uint8_t*) &value, ((uint8_t*) &value) + sizeof(T), std::back_inserter(_buffer)); 
    return *this; 
} 

現在你可以寫任何POD類型到您的緩衝區。

含蓄:

int i = 5; 
o.write(i); 

或顯式:

o.write<int>(5); 

爲了從緩衝區讀取,您將需要保持一個讀取位置的軌跡:

template <class T> 
T read() { 
    T result; 
    uint8_t *p = &_buffer[_rpos]; 
    std::copy(p, p + sizeof(T), (uint8_t*) &result); 
    _rpos += sizeof(T); 
    return result; 
} 

您需要顯式傳遞一個類型參數來讀取。即

int i = o.read<int>(); 

警告:我經常使用這種模式,但由於我打字這個從我的頭頂,有可能是代碼的一些錯誤。

編輯:我只是注意到,你想能夠添加字符串或其他非POD類型到您的緩衝區。你可以做到這一點通過模板特:

template <> 
Packet& add(std::string s) { 
    add(string.length()); 
    for (size_t i = 0; i < string.length(); ++i) 
     add(string[i]); 
    return *this; 
} 

這告訴編譯器:如果添加被稱爲一個字符串類型,使用此功能,而不是一般的add()函數。

和閱讀的字符串:

template <> 
std::string read<>() { 
    size_t len = read<size_t>(); 
    std::string s; 
    while (len--) 
     s += read<char>(); 
    return s; 
} 
+0

但是,我需要一個單獨的函數來讀取字符串,因爲這些函數可以是可變長度的。 感謝您的代碼,我現在就試試看。 – 2010-04-28 12:45:40

+0

我剛試過,添加部分得到一個段錯誤,找出原因的時間... – 2010-04-28 12:48:40

+0

我沒有看到任何錯誤:/ – 2010-04-28 12:49:34

1

你可以使用std::string內部緩衝區,並添加新的元素時使用append()

因此,添加字符串或const char *將是微不足道的。

添加/寫入uint8可以通過將其轉換爲char,將uint16 - 寫入長度爲sizeof(uint16_t)的char *來完成。

void write_uint16(uint16_t val) 
{ 
    m_strBuffer.append((char*)(&var), sizeof(val)); 
} 

閱讀UINT16:

uint16_t read_int16() 
{ 
    return (*(uint16_t*)(m_strBuffer.c_str() + m_nOffset)); 
} 
0

你似乎是試圖打印10個字節移出緩衝區時,你只增加了四個,這樣的話你要逃跑的矢量結束。這可能會導致您的seg故障。

此外,您的printf正嘗試將字符打印爲帶有%x的無符號整數。您需要使用static_cast<unsigned>(packet._buffer[i])作爲參數。

風格: Packet packet = Packet();可能會導致兩個對象被構造。只需使用Packet packet;

通常嘗試避免受保護的屬性(受保護的方法很好),因爲它們會減少類的封裝。

+0

不會導致段錯誤,它印刷得很好,出於某種奇怪的原因。我現在已經轉向使用Ferruccio提出的模板,並且工作得很好,剩下的就是字符串的讀取功能。 – 2010-04-28 13:42:34

相關問題