Re: working with bits
On Apr 18, 5:16 am, Jerry Coffin <jcof...@taeus.com> wrote:
In article <1176864688.919444.214...@n76g2000hsh.googlegroups.com>,
iwasinni...@hotmail.com says...
I am still working on this project (Creating a DNS resolver). My
programming skills have a lot to be desired. I need to combine 4
buffers together and then use the sendto() socket command to send the
message to the DNS server. Here are my buffers. The message needs to
be a char*.
unsigned int header_buffer = (ID << 80) | (Flags.Flag << 64) |
(QDCount << 48) | (ANCount << 32) | (NSCount << 16) | ARCount;
I'm not sure what hardware you're working on, but it looks
pretty exotic, if you have over 80 bits in an int.
unsigned char QNAME;
unsigned __int16 QTYPE;
unsigned __int16 QCLASS;
I am at a loss as to how to combine these and then get it converted
into a char* so that I can use sendto().
Typically you'd do something like:
struct name_def {
unsigned int header_buffer = (ID << 80) | // ...
// (ID << 80)? Really?
unsigned char QNAME;
unsigned _int16 QTYPE;
unsigned _int16 QCLASS;
};
I rather doubt that this would work either. The compiler will
probably insert some padding between QNAME and QTYPE. And
whether the internal format of __int16 corresponds to what is
required on the line or not is not at all defined. (__int16
looks like some old Microsoft stuff. In which case, he's
probably on an Intel based PC, and the internal format does
*not* correspond to line format.)
In practice, you have to build up a byte buffer, byte by byte,
as I explained in my earlier answer. And respect the external
format in all cases; QNAME is in fact a string, in the format
one byte length+characters; I suspect that it also has to be
padded to align to either 2 or 4 bytes (but I've not verified in
detail)---if not, QTYPE and QCLASS might be mis-aligned. At any
rate, QNAME is a variable length field, so there's no way you
can use a struct here, even if all internal fields had the
correct format.
The way I usually handle this sort of thing is with push_back,
into an std::vector<char>; I then consider byte by byte what I
have to insert. (Alignment can be handled using the % operator
on v.size().) In some cases, where e.g. I have to insert the
number of bytes in what follows, I'll simply note the current
offset (v.size()), insert a placeholder, and then come back
later and write the actual value. Finally, I'll write &v[0],
v.size().
Obviously, this requires a fairly good understanding of the
lower levels of what is going on. I'd say that that is a
pre-requisite, however, for implementing any Internet protocol.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34