2011-08-21 5 views
1

나는 네트워킹으로 놀고 있는데, 나는 많은 값의 패킷을 내가 원하는 값으로 변환하면서 약간의 도로 블록을 쳤다.문자 배열의 번역/형변환 부분을 값으로 바꾸기

기본적으로 나는 내 패킷이 조금 보이기를 기대하는 패킷을 만들었습니다. 본질적으로 메시지가 무엇인지 나타내는 Char (8 비트 값)이며 스위치 문에서 감지하여 해당 8 비트 값 다음의 데이터를 기반으로 값을 채 웁니다. 내 패킷에는 순서에 있지 않을 수도있는 모든 종류의 메시지가 포함될 것으로 예상됩니다.

예, 나는 등 끝에 심장 박동, 또는 채팅 메시지의 텍스트 문자열로 끝낼 수

난 그냥 내 프로그램으로 말할 수있을 a로부터 데이터를 먹고 싶어

char 배열의 특정 포인트와 타입 변환 (원하는 경우)? 그렇게하는 쉬운 방법은 무엇입니까? Clairvoire의 아이디어에 따라

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

나는 다음을 추가했습니다.

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

공지 사항 나는 시프트 값을 변경했다. 나는 음의 값을 받고 된 각 요소의 결합과 혼합되고, 그렇게하지 않은 경우

또 다른 중요한 변화는

unsigned char bufferIncoming[15] 

이었다. 나는 컴파일러가 후드에서 무엇을하고 있었는지 모르지만 피투성이였다.

내가 상상할 수있는 것처럼 이것이 내 선호하는 해결책은 아니지만 한 번 사용해 보도록하겠습니다. "차드 (Chad)"는 어떻게 구조화 할 수 있었는지에 대한 좋은 예를 보여 주었고 직장 동료 프로그래머도 구현을 권장했습니다. 하지만 ...

나는 내가 원하는 것을 더 빠르고 깨끗하게 처리해야한다는 느낌을 가지고 있습니다. 나는 같은 것을 시도했다 ...

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 버퍼의 어딘가를 가리키며 "hey 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

안녕하세요. –

+0

"position.Y = * ((long int *) buffer + 9);"를 사용하여 편집에서 마지막으로 언급 한 내용을 수행 할 수 있습니다. 나는 믿는다. 그러나 방해가되는 것은 엔디안이다. 통신하는 두 대의 컴퓨터가 서로 다른 엔디안을 사용하는 경우 컴퓨터 A는 정수를 ABC D의 4 바이트로 저장합니다. 수신 컴퓨터는이 4 바이트를 다시 DCB A로 저장합니다. –

답변

0

같이 보일 것이다 비트를 사용하여 정수를 분할의 예는 내가 스카이프에 알고있는 프로그래머 중 하나에 이야기했고 그는 나에게 내가 찾던 솔루션을 보여 주었다.

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; 

엔디안을 에스 bitwise 논리는 항상 오른쪽에서 가장 낮은 순서로 (같은 자리가 십진수 오른쪽에있는 것과 같이) 실행되므로 걱정할 필요가 없습니다.

편집 : 엔디 언은 요소에 따라 달라질 수 있습니다. 전송기가 네트워크를 통해 전송하기 전에 정수를 처음으로 어떻게 분할하는지에 대한 정보. Shift 키를 사용하여 다시 구성 할 때와 같은 방법으로 정수를 분해하지 않으면 첫 번째 바이트가 마지막이고 마지막 바이트가 첫 번째 인 값을 얻을 수 있습니다. 이것들과 같은 작은 모호성 때문에 네트워킹 라이브러리를 가장 많이 사용하게됩니다.

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

위의 코드 예제는 값을 mucks 비트 그래서 나는 그것으로 작동하도록 주변 놀아야했다. 위의 편집 내용을 참조하십시오. – ChiggenWingz

+0

@chiggenWingz 죄송합니다. 먼저 코드 예제를 테스트했거나 최소한 의사 코드라고 했어야합니다. 그러나 작동하도록되어있어서 다행입니다. 나는 다른 사람이 나에게 곧 나올 것이라고 확신하지만 4 바이트 정수를 만들기 위해 4 바이트 정수를 결합하는 목표를 달성하기 위해 노력하고 있음을 지적한다. 귀하의 구체적인 경우에는 Chad 's 및 귀하가 얻는 다른 답변과 같은 네트워킹에 대한 더 나은 대안이있을 것입니다. –

+0

글쎄 엔디 언은 항상 바이너리 (텍스트와 반대) 직렬화 된 표현에서 중요한 문제입니다. 귀하의 코드는 LS 바이트를 먼저, MS 바이트를 마지막으로, 즉 리틀 엔디안 규칙으로 가정합니다. 그것이 당신의 대회라면, 그러면 좋습니다. –

관련 문제