2010-08-18 9 views
3

이더넷 헤더와 함께 전체 UDP 패킷을 표현하기로되어있는 구조체가 있습니다. 여기입니다 : 물론바이트를 건너 뛰는 구조체의 필드

#pragma pack(1) 
struct UDPPacket { 
    // an array to hold the destination mac address of the packet 
    unsigned char dstmac[6]; 

    // an array to hold the source mac address of the packet 
    unsigned char srcmac[6]; 

    // two bytes to hold the packet type, this is almost always IP (08 00) 
    WORD ethtype; 

    // each of the subfields of this take up 4 bits. ver, the first half, 
    // is the ip version, which should usually be 4 for ipv4, and the second 
    // is the length of the header divided by 4, which is almost always 5 
    struct { 
     unsigned ver : 4; 
     unsigned len : 4; 
    } verlen; 

    // this isn't used in ipv4 and is 0 
    BYTE tos; 

    // the total length of the header + data 
    WORD iplen; 

    // the id of this datagram for reassembling fragmented packets 
    WORD id; 

    // the first subfield occupies 3 bits and is the flags of this packet, which is usually 0 
    // the second subfield is the fragmentation offset for large datagrams that have been split up for sending, usually 0 
    struct { 
     unsigned flags : 3; 
     unsigned fragmentation : 13; 
    } flagfrag; 

    // time to live; usually 35 or 128 
    BYTE ttl; 

    // the protocol with which this packet is being transported 
    // 1 = ICMP, 2 = IGMP, 6 = TCP, 17 = UDP 
    BYTE protocol; 

    // the ip checksum of this packet 
    WORD ipchecksum; 

    // the source ip of this packet 
    DWORD src; 

    // the destination ip of this packet 
    DWORD dest; 
    // the port from which this packet is coming 
    WORD srcport; 

    // the port this packet is headed to 
    WORD destport; 

    // the length of the udp header + data, not including the ip header 
    // so it's usually basically iplen - 20 
    WORD udplen; 

    // the udp checksum of this packet 
    WORD udpchecksum; 

    // a char pointer to the data of the packet 
    unsigned char data[10000]; 
}; 
#pragma pack() 

이 실제 UDP 패킷의 표현되고, 바이트들은 패킷에있을 것 같은 동일한 오프셋에서해야하고, 구조체의 이러한 유형에 대한 포인터가 될 것입니다 전송을 위해 unsigned char*로 전송하십시오.
내 문제는 UDPPacket.verlen 뒤에 아무 것도 지정하지 않으면 약 5 바이트 건너 뛰고 거기서 시작된다는 것입니다. 예를 들어 오프셋 16과 17에서 바이트를 설정하는 대신 iplen feild를 할당하면 23과 24와 같이 할당됩니다 (정확하게 내 전화에서 내 프로그램을 사용할 수 없기 때문에 정확하게 말할 수 없습니다).).
누락 된 이유가 있습니까? 아니면 잘못되었습니다.

+0

그리고 Visual Studio 2008을 x64 Windows 7에서 사용하고 있지만 x86 용으로 컴파일하고 있습니다. – Hock

답변

2

#pragmas보기. Bitfields는 명시 적으로 지정된 비트 수에 맞는 가장 작은 유형으로 "자동 압축"하지 않습니다. 나는 verlen이 당신의 주어진 타입을 "unsigned"라고 생각하고 그것이 컴파일러에서 32 비트처럼 들리는 unsigned int 크기의 bitfiend라고 가정한다. 대신 verlen "unsigned char"필드를 작성하십시오.

여기 더 있습니다. 여기에 "서명되지 않은 char"을 지정하는 기능은 (ANSI C에 대한) MSFT 확장이지만 작동해야합니다 : http://msdn.microsoft.com/en-us/library/yszfawxh(VS.80).aspx

N.B. 여기에 flagfrag에 대해 동일하게 적용됩니다.이 값은 "unsigned short"여야합니다.

+0

전에 필자는 그것이 차지해야 할 비트 수를 지정했기 때문에 어떤 유형인지는 중요하지 않다고 생각했지만, 이제는 특정 바이트 수를 차지하는 형식을 지정한다고 생각합니다.), 당신은 구조체 내에 서로 다른 비트 필드를 가질 수 있습니다. 그 맞습니까? – Hock

+0

저는 이것이 C++에서 확장 기능이 아니라 표준의 요구 사항이라고 믿습니다. 조심스럽게 다시 문법을 거쳐야 할 것입니다. 나는 오늘 밤 나중에 시도해 볼 수도 있습니다. –

+0

예, 근본적으로 컴파일러는 비트 필드로 사용하는 기본 유형에만 신경을 씁니다. 개별 비트의 이름을 지정하는 기능은 사용자에게있어 구문상의 편의입니다. 새로운 "비트"유형 또는 그와 비슷한 것을 도입하지는 않습니다. 그것이 구조에서 비트 필드의 중간에 전체 작은 유형을 가질 수 있다고는 생각지 않지만 (시도해 보거나 문서를 읽어야한다고는하지만) 그렇게하는 것이 쉬운 일이 아닙니다. –

0

컴파일러의 패딩 및 정렬 설정을 확인해야합니다.

1

표준에서는 컴파일러가 비트 필드를 단일 저장 단위 (int, char, anything)로 패킹하지 않아도됩니다. 그래서 프라그 마를 사용하더라도 2 비트 필드가 2 문자 또는 정수를 차지할 것으로 기대합니다. 그 컴파일러에 대한 문서가 없습니다 - 플러그인이 비트 필드에 어떻게 영향을 주는지 말합니까?

1

귀하의 #pragma pack 지시어는 바로,하지만 난 당신의 bifields (verlenflagfrag)의 기본 유형 대신 charint을하고 short 당신이 기대했던 것 같아요.

0

unsigned은 여기서는 unsigned int과 동일하며 4 바이트입니다. 따라서 iplen은 오프셋 23에 있어야합니다.

관련 문제