2011-08-21 49 views
1

我在玩網絡遊戲,並且將一大堆數據的數據包轉換爲我想要的數值的路塊。想要將字符數組的部分轉換/值轉換爲值

基本上我已經做了一個我期待我的數據包看起來有點樣子的樣機包。本質上是一個Char(8位值),表示消息是什麼,然後由switch語句檢測到,然後在該8位值之後根據數據填充值。我期待我的信息包裏有各種信息,而這些信息可能並不合適。

例如,我可以結束與心跳末,或從聊天消息的文本字符串,等等

我只是希望能夠告訴我的計劃,請從數據字符數組和特定字符串中的某個點(如果這是它的術語?)將它們變成我想要它們的東西。什麼是一個很好的簡單的方法來做到這一點?

char bufferIncoming[15]; 
ZeroMemory(bufferIncoming,15); 

//Making a mock packet 
bufferIncoming[0] = 0x01; //Heartbeat value 
bufferIncoming[1] = 0x01; //Heartbeat again just cause I can 
bufferIncoming[2] = 0x10; //This should = 16 if its just an 8bit number, 

bufferIncoming[3] = 0x00; // This 
bufferIncoming[4] = 0x00; // and this 
bufferIncoming[5] = 0x00; // and this 
bufferIncoming[6] = 0x09; // and this should equal "9" of its is a 32bit number (int) 

bufferIncoming[7] = 0x00; 
bufferIncoming[8] = 0x00; 
bufferIncoming[9] = 0x01; 
bufferIncoming[10] = 0x00; //These 4 should be 256 I think when combines into an unsigned int 
//End of mockup packet 


int bufferSize = 15; //Just an arbitrary value for now 
int i = 0; 
while (i < bufferSize) 
{ 
    switch (bufferIncoming[i]) 
    { 
     case 0x01: //Heart Beat 
      { 
       cout << "Heartbeat "; 
      } 
      break; 
     case 0x10: //Player Data 
      { 
       //We've detected the byte that indicates the following 8 bytes will be player data. In this case a X and Y position 

       playerPosition.X = ??????????; //How do I combine the 4 hex values for this? 
       playerPosition.Y = ??????????; 
      } 
      break; 
     default: 
      { 
       cout << "."; 
      } 
      break; 

    } 
    i++; 
} 
cout << " End of Packet\n"; 


UPDATE

繼Clairvoire的想法,我增加了以下內容。

playerPosition.X = long(bufferIncoming[3]) << 24 | long(bufferIncoming[4]) << 16 | long(bufferIncoming[5]) << 8 | long(bufferIncoming[6]); 

注意我改變了移位值。

另一個重要變化是

unsigned char bufferIncoming[15] 

如果我不這樣做,我得到負值每個單元的組合混合。我不知道編譯器在引擎蓋下做了什麼,但是它讓人感到非常討厭。

正如你可以想象,這不是我的首選解決方案,但我會給它一個去。 「乍得」就是一個很好的例子,我可以如何構建它,而另一位工作程序員也推薦他的實現。但...

我有這種感覺,必須有更快更乾淨的方式做我想做的事情。我試過類似的東西...

playerPosition.X = *(bufferIncoming + 4) //Only giving me the value of the one hex value, not the combined >_< 
playerPosition.X = reinterpret_cast<unsigned long>(&bufferIncoming); //Some random number that I dont know what it was 

..和其他一些我刪除的東西也沒有工作。我期望做的事情是指出char buffer的某處,並說「嘿playerPosition,從這個位置開始閱讀,然後根據字節數據填寫你的值。」

如也許......

playerPosition = (playerPosition)bufferIncoming[5]; //Reads from this spot and fills in the 8 bytes worth of data 
//or 
playerPosition.Y = (playerPosition)bufferIncoming[9]; //Reads in the 4 bytes of values 

...爲什麼犯規它的工作一樣,或者類似的東西?

+0

G'night給你。 –

+0

你可以通過使用「position.Y = *((long int *)buffer + 9)」來完成你在編輯中最後提到的內容;「我相信,但有一點是阻礙。如果兩臺計算機通信有不同的端點,將發生什麼情況是計算機A會將該整數存儲爲四個字節,即ABC D.然後,接收計算機將這四個字節重新組合爲DCB A. –

回答

0

分裂整數的一個例子是說,我知道Skype上的程序員之一,他向我展示了我一直在尋找的解決方案。

playerPosition.X = *(int*)(bufferIncoming+3); 

我不記得如何得到它的工作,或者是它的調用。但現在看來一切都很好。

謝謝你們幫忙:)

0

在典型的消息傳遞協議中,最直接的方法是使用繼承(或組合)和字節對齊結構(對於從此處的原始數據指針進行投射很重要),可以輕鬆地投射一組消息情況下)可以使這個相對容易:

struct Header 
{ 
    unsigned char message_type_; 
    unsigned long message_length_; 
}; 

struct HeartBeat : public Header 
{ 
    // no data, just a heartbeat 
}; 

struct PlayerData : public Header 
{ 
    unsigned long position_x_; 
    unsigned long position_y_; 
}; 

unsigned char* raw_message; // filled elsewhere 

// reinterpret_cast is usually best avoided, however in this particular 
// case we are casting two completely unrelated types and is therefore 
// necessary 
Header* h = reinterpret_cast<Header*>(raw_message); 

switch(h) 
{ 
    case HeartBeat_MessageType: 
    break; 

    case PlayerData_MessageType: 
    { 
     PlayerData* data = reinterpret_cast<PlayerData*>(h); 
    } 
    break; 
} 
1

有可能是這樣一個漂亮的版本,但我個人會使用四個字符變量左移和ORS像這樣結合:

playerPosition.X = long(buffer[0]) | long(buffer[1])<<8 | long(buffer[2])<<16 | long(buffer[3])<<24; 

字節序小號因爲按位邏輯總是執行相同的,右邊的最低順序(比如右邊的十進制數字如何放置)

編輯:字節順序可能會成爲一個因素關於發送機器在通過網絡發送之前最初是如何拆分整數的。如果它不像使用移位重構它一樣分解整數,則可能會得到一個值,其中第一個字節是最後一個字節,最後一個字節是第一個字節。像這樣的小模糊可以促使大多數人使用網絡庫,哈哈。

使用逐會是這個樣子

buffer[0] = integer&0xFF; 
buffer[1] = (integer>>8)&0xFF; 
buffer[2] = (integer>>16)&0xFF; 
buffer[3] = (integer>>24)&0xFF; 
+0

上面的代碼示例將值a所以我不得不玩弄它來使它工作。看到我上面的編輯 – ChiggenWingz

+0

@chiggenWingz對不起,我應該首先測試該代碼示例,或者至少說它是僞代碼,但我很高興你能夠使用它。不過,我應該指出,因爲我確信別人會盡快給我,這只是爲了實現將四個字節組合成整個4字節整數的目標。對於您的具體情況,可能有更好的替代方案,比如乍得的網絡以及您獲得的任何其他答案。 –

+0

良好的字節順序始終是二元(而不是文本)序列化表示的問題。你的代碼簡單地假定LS字節在先,MS字節在最後,即小端約定。如果這是你的慣例,那很好。 –