-
[RESOLVED] Bits, Bytes and Boomerangs (without the boomerangs...)
Sorry, I like my thread titles with alliteration :D
Anyway... now that you think I'm weird, lets get down to business.
As per this thread: http://www.vbforums.com/showthread.php?t=584412 I am trying to perform a DNS query in code. Having spent the last few hours trying to get my head around this and failing miserably I figured I would see if anyone on here could point me in the right direction.
The DNS RFC (http://www.faqs.org/rfcs/rfc1035.html) tells me that the header of each UDP packet that contains a DNS query should look like this:
Code:
The header contains the following fields:
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
So we have got 16 bits (which I believe is 2 bytes) available for each section of the header, but as you can see the second section of the header is not just a nice full 2 byte value - its several individual bit values (with a couple of 4 bit values as well) and its this that is tripping me up at the moment.
I'm not great with Bytes, let alone Bits, so I'm pretty stuck with trying to work out how I can 'set' the relevant Bits and then combine the whole thing to make a Byte array that is 12 Bytes long.
I'm not even sure if I am setting the values correctly for the sections of the header that are 2 full bytes. Here is what I am doing at the moment, I'm using a List(Of Byte) with the intention of just calling ToArray when I have finished building it... because although the header is 12 bytes long, the rest of the packet has a variable length so I thought this would be easier than lots of ReDiming of a Byte array but feel free to tell me if thats a stupid idea :)
vb.net Code:
Dim UDPClt As New UdpClient(53, AddressFamily.InterNetwork)
Dim QuestionBytes As New List(Of Byte)
'<--Construct Header-->
'ID
QuestionBytes.Add(10)
QuestionBytes.Add(10)
'Parameters
'-- This is the part that I need help with the most --
QuestionBytes.Add(some bits!)
'QDCOUNT
QuestionBytes.Add(0)
QuestionBytes.Add(1)
'ANCOUNT
QuestionBytes.Add(0)
QuestionBytes.Add(0)
'NSCOUNT
QuestionBytes.Add(0)
QuestionBytes.Add(0)
'ARCOUNT
QuestionBytes.Add(0)
QuestionBytes.Add(0)
'</--Construct Header-->
Is that even the right way to add bytes to a byte array - I mean can you add an item to a Byte array just using an Integer as the input or am I doing it wrong and I need to use some conversion? I'm surprised I didnt need to use CByte to keep Option Strict happy but maybe thats just because Bytes are still a bit of a mystery to me... (hopefully this will be a good learning experience).
I'm currently looking into the BitArray class but not getting anywhere fast and not even sure if thats what I should be doing so any pointers would be more than welcome!
Also, the other 2 byte sections in the header are defined as "An unsigned 16 bit Integer" but in the examples of DNS queries I have seen these fields are just set to 01 or 00 so can I get away with just writing two bytes as I am doing in my example code above? Does that equate to the same as a 16 bit unsigned integer?
Thanks :)
Chris
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
You use division to move the bits you want to bit 0. Divide by a power of 2.
Then you use a mask to "only" allow your bits to come through.
4 bits is a nibble.
I'll work up a quick example for you.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Originally Posted by
szlamany
You use division to move the bits you want to bit 0. Divide by a power of 2.
Then you use a mask to "only" allow your bits to come through.
4 bits is a nibble.
I'll work up a quick example for you.
Is "a nibble" a good thing or a bad thing in this context? :)
I also just noticed that one of the values in that second section is actually 3 bits (so there are two 4 bit values, one 3 bit value, and a few single bit values)
An example would be great thanks as I have no idea what you are talking about :thumb:
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Ok - this is the first pass - how the value is built. Next post will show you how to extract it. OR is really used as a operator - that's binary addition.
Code:
Ok - let's say we got this pattern
|__|__ __ __|__ __ __ __| - this is my byte
0 1 2 3 4 5 6 7
1 2 4 8 16 32 64 128
I've broken it into a bit, then a 3-bit area, then that last 4-bit high order nibble.
And of course I want to store values in these areas - but the values are real numbers - starting at 1, right?
So the first bit - we will call that a flag - it's either on or off
The next 3 bits - they are a value that is 3 bits (1,2,4) and if I want to store 5 in that area I would put 101 (1 + 4 = 5).
The next 4 bits - another value - and lets say I want to store a decimal value of 10 in that area - that would be 0101 (2 + 8 = 10).
So in the long run I want to store this:
Code:
myByte = 1 (sets the first bit)
myByte = myByte OR (5 * 2)
' 5 is what I want to store - multiply it by 2 and it shifts to that location
myByte = myByte OR (10 * 16)
' 10 is what I want to store - multiply it by 16 and it shifts to that location
myByte should be equal to 1 + 10 + 160 which is 171 - right?
Now let's see what that 11010101 is equal to in decimal
Code:
1 1 0 1 0 1 0 1
1 2 8 32 128
1+2+8+32+128=171
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Ok - now this is really simple - let's show you how to get that middle 3-bit item out of the byte
First shift down - and 2 is the shift spot - that's what we multiplied by - remember?
my3Bit = myByte / 2
These have to be integer variables - so 171 / 2 (in an integer fashion) yields 85.
And of course 85 is
Code:
1 0 1 0 1 0 1
1+4+16+64=85
I've shifted my 3-bit and my nibble down - got rid of my first bit with that division.
Now I need to mask it
my3Bit = my3Bit AND 7
7 is 111
When you use the AND operator it only allow bits set in both integers to be seen
Code:
7 is 11100000
85 is 10101010
yields 10100000
The AND will only allow the 101 to come through - that's the use of the AND operator.
That mask we created of 111 (which is decimal 7) clears out the other bits in the resulting variable.
When you want to mask that nibble you use 1111 (which is decimal 15).
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Firstly, thanks :) Secondly, I didnt realise nibble was an actual technical term haha I thought you were just saying "thats a nibble" as in "that will be easy" or something... I dunno. Thirdly, I didnt understand half of that on the first read through so I will re-read it a few times and post any questions :)
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
OK I've read both posts 3 times now and I'm still a little confused (but getting there...)
The thing I'm struggling with is working out how you know that setting 101 in the 3 bit section will equal 5. From looking at the numbers you have written below each bit I would have thought 101 in that second section would equal either 1 + 3 or 2 + 8 (why are there 2 numbers beneath each bit by the way?)
Also, when you are just setting the entire Byte to 1 at the start - that means that setting a Byte to the Integer 1 and setting the first Bit of a Byte to 1 and the rest to 0 is the exact same thing yeah? but does it also mean that setting any Bit in the Byte to 1 is the same as just setting the Byte to 1? The reason I ask because the first bit field (I'm just referring to the second section of the DNS header in my original post) is defined as:
Quote:
QR
A one bit field that specifies whether this message is a
query (0), or a response (1).
so that needs to be 0, as do most of the other bits for my query, but then this RD field (bit number 7) needs to be 1. So if I just add a Byte of 1 is that going to do the same thing as if I just set the seventh Bit of that Byte to 1? Hope that makes sense
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
OR sets a bit
AND is a mask for a bit
AND NOT clears a bit
101 is 5 because the bits are worth 1, 2, 4, 8 and so on.
101 is 1 + 4 - the 2 is missing.
You should really sit in the immediate window and do some
? 1 OR 4
? 5 AND NOT 4
? 5 * 2
and so on...
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
101 is 5 because the bits are worth 1, 2, 4, 8 and so on.
101 is 1 + 4 - the 2 is missing.
But when you set the second bit in the Byte to 1, how does it know you want the value 1 and not the value 2 - there isnt actually anything telling it that we are grouping those 3 bits together is there?
Lets modify your example a bit, split it up into different bit fields like so:
Code:
|__ __|__ __|__ __ __ __| - this is my byte
0 1 2 3 4 5 6 7
1 2 4 8 16 32 64 128
So now if we say that those same bits (bit 2, 3 and 4) are set to 1,0,1 respectively then does that mean they now produce a different value to your first example because they are in different 'sections'? I just dont understand where you are getting 1 + 4 from as the numbers you have written below the diagram do not place 1 and 4 under the 2nd and 4th bit
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
You broke it into a word, word and nibble. The first two words won't fit anything more then a 2-bit value.
If I want to store 5 in the high order nibble then I need to shift it up
5 in the low order nibble is
1010 0000
right? That's a 1 + 4.
If I want it up in the high order - looking like this
0000 1010
then I multiply the low-order 5 by the bit-value if that pivot spot - that's the 16 spot. 5 * 16 is 80 - right?
and of course
0000 1010
that 16 + 64 - that's 80!
I'll discuss your two low order words in the next post...
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Ok - those low order words you created can only store 2-bit values. And in two bits you can only store 0, 1, 2 or 3 (decimal) - 11 is 3, 01 is 2, 10 is 1 and 00 is 0 (just to show all combinations).
So I want to store a 2 in the first-low order word. And I want to store a 3 in the second low order word. And I want to store that 5 in the high order nibble.
That's going to look like
0111 1010 (decimal 94)
Do you see that?
2+4+8 along with 16+64 - for a total of decimal 94
Now to see a word - I first shift it to the down and then mask it with a WORD mask. A WORD mask is a 3 (11).
And of course to mask a nibble we use 15 (1111).
I'll do this in the immediate window:
Code:
myByte = 0
myByte = myByte OR (2) ' store a 2 in the low order
myByte = myByte OR (3 * 4) ' store a 3 in the next word (4 is the shift point)
myByte = myByte OR (5 * 16) ' store a 5 in the high order nibble
? mybyte
94
'it's really a 94 - built in the fashion I've just shown
?(mybyte \ 16) AND 15 ' I'm using \ to force integer division
' if you have 16 as an INTEGER constant the math will remain INTEGER
5
?(mybyte \ 4) AND 3
3
?(myByte) AND 3
2
You just saw me take the 94 in the myByte variable and do three different shifts with 2 different masks and you saw my original values of 5, 3 and 2.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
OK I think I'm getting the hang of it, thanks for the example. I'll have a play around in the immediate window and see if I still have any questions :)
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Keep in mind that all this shifting is for looking at several bits from anywhere in the byte as if they were a real value living at bit 0.
Setting a bit or clearing a bit does not involve division - it's just using of OR or AND NOT.
Code:
myByte = myByte OR 4 ' this sets the bit at position 2
myByte = myByte AND NOT 4 ' this clears the bit as position 2
If you are going to do a lot of this create a constant for Bit$0 and Bit$1 and Bit$2 all the way up to Bit$15 or Bit$31 - whatever you want.
Beware of floating point math in all this - you don't want to accidently fall out of the integer datatypes.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
OK thanks, while I still try to get my head around it and test things out can you just explain this to me:
In your example you show 2 numbers below each bit.
Code:
|__|__ __ __|__ __ __ __| - this is my byte
0 1 2 3 4 5 6 7
1 2 4 8 16 32 64 128
How does it know which number you wanted? Why are there 2 numbers below each one?
Actually looking at it again, were those top numbers (0 - 7) purely there for reference to show which bit the number below was referring to? I thought they were part of this whole thing... but if its just the bottom row of numbers I need to be aware of then that makes things a bit clearer
Thanks
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Originally Posted by
chris128
In your example you show 2 numbers below each bit.
Code:
|__|__ __ __|__ __ __ __| - this is my byte
0 1 2 3 4 5 6 7
1 2 4 8 16 32 64 128
2 ^ 0 power is 1
2 ^ 1 power is 2
So Bit 0 is decimal value 1
and Bit 2 is decimal value 2
3 is 4
4 is 8
5 is 16...
2 ^ 7 power is 128
Back in my mainframe days we would have constants called Bit$0 which were equal to a 1 and Bit$1 equal to a 2 and Bit$2 equal to a 4.
But I can still recite powers of 2 from memory on demand!
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Yeah I get that but that is the bottom row of numbers, I am asking what the top row referes to (12345678)? Were you just using it to show which bits were which or are those numbers actually part of anything I need to know?
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Top row is 0, 1, 2, 3, 4, 5, 6 and 7
Bottom row is 1, 2, 4, 8...128
That is the "power" in the top row and the "decimal" value in the second row.
That's all - 2 ^ 0 is bit 0 and is decimal value 1
Just a way for me to label the byte - normal I would have put just 0, 1, 2...7
The real reason for that is to show low-order position vs high-order position. There are places that you will see the low on the left and some that put the high on the left.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Just a way for me to label the byte
Ahhh I see! That was confusing me as I thought it was used in your explanation - although technically it is as the numbers below are the power of 2 of those top numbers like you said, but I only really need to know the bottom row as thats what dictates what each bit represents in decimal, right?
Also can you just clarify what you mean by high order and low order? Is it simply that the first 4 bits are low order and the last 4 bits are high order? You said that some people show them the other way round, if thats the case then how do you know which is which when its all just 1s and 0s ?
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Originally Posted by
chris128
Ahhh I see! That was confusing me as I thought it was used in your explanation - although technically it is as the numbers below are the power of 2 of those top numbers like you said, but I only really need to know the bottom row as thats what dictates what each bit represents in decimal, right?
Exactly.
Even your example in the first post uses the 0, 1, 2 ... 15 as column labels. You have to somehow tell a person what bit is bit 0 and which is bit 15.
I added the row of 1,2,4,8 - the decimal row - to help you quickly understaned why I dividing by 16 or multiplying by 16 to shift something out and back into bit 4 position.
Quote:
Also can you just clarify what you mean by high order and low order? Is it simply that the first 4 bits are low order and the last 4 bits are high order? You said that some people show them the other way round, if thats the case then how do you know which is which when its all just 1s and 0s ?
The 0 in the 0...15 (or 0...7) heading tells you the low order bit. You first need to know that to understand how they are orienting the key you are looking at.
When I refer to a high-order nibble when talking about a byte - since there are only two nibbles in a byte you know I'm talking about bits 4 to 7.
If I refer to the low-order word of a byte then I'm talking about 0 to 1. The high-order word of a byte is 6 to 7. No real way to use that lingo to talk about the word at 2 to 3. I guess that's the "high order word" in the "low order nibble" of a byte.
High and low really refer to left and right but since people notate bits with 0 on the left and others with 0 on the right I guess low and high became the best way to talk about which side of the byte we are discussing.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
OK I think I get it, so just to confirm - this example from another website explaining bits:
Quote:
With 8 bits in a byte, you can represent 256 values ranging from 0 to 255, as shown here:
0 = 00000000
1 = 00000001
2 = 00000010
...
254 = 11111110
255 = 11111111
They are doing it the other way round to your example yeah? high order first. Surely its important which order VB.NET uses though when you are working with bits in the way that I need to? Does it use high order first or low order? Or doesnt it matter..
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Originally Posted by
chris128
They are doing it the other way round to your example yeah? high order first.
safer to say high order left - since we are really talking for your "visual indication". But yes - you are correct - they are using the more "traditional" method of show bit 0 - value 1 - as the first upper-right bit in the display.
Quote:
Surely its important which order VB.NET uses though when you are working with bits in the way that I need to? Does it use high order first or low order? Or doesnt it matter..
It doesn't matter - this is all about visual representation on paper.
You in VB are using AND, AND NOT and OR with decimal values anyway - if you want to remove bit 0 you say
x = x AND NOT 1
or
x = x AND NOT (2 ^ 0) 'if you like to "see" the bit in the expression
or
x = x AND NOT BIT$0
and you define BIT$0 as a value of 1 in some module somewhere.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
It doesn't matter - this is all about visual representation on paper.
I dont understand how it cant matter. Lets say I construct the following byte in VB:
If VB thinks that is high order left then that that means we have set bit 2 and all other bits are not set, so that means we have set a value of 4 yes?
If VB thinks that sequence is high order right (as in your original example) then we have set bit 5 so the value would be 32 wouldnt it?
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
OK so I had a stab at doing what I wanted to do originally - build this DNS header.
This is the table I am working with remember
Code:
The header contains the following fields:
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
and this is my code now:
vb Code:
Dim HeaderBytes(11) As Byte
'--ID
HeaderBytes(0) = 55
HeaderBytes(1) = 65
'--Parameters
'First byte of parameter section
Dim FirstParametersByte As Byte = 0
FirstParametersByte = CByte(FirstParametersByte Or (1 * 128))
HeaderBytes(2) = FirstParametersByte
'Second byte of parameter section
HeaderBytes(3) = 0
'--QDCOUNT
HeaderBytes(4) = 0
HeaderBytes(5) = 0
'--ANCOUNT
HeaderBytes(6) = 0
HeaderBytes(7) = 0
'--NSCOUNT
HeaderBytes(8) = 0
HeaderBytes(9) = 0
'--ARCOUNT
HeaderBytes(10) = 0
HeaderBytes(11) = 0
What I am aiming for is for the RD bit in the second field (which I have posted in red font in the table above) to be set to 1, and the first field (the ID field) to be set to 5565 as this can apparently just be any 2 byte value. All other bits should be 0. Will that code I have got achieve that?
EDIT: Actually no sorry, I need to have the following in the QDCOUNT section:
Quote:
an unsigned 16 bit integer specifying the number of
entries in the question section.
so as there is just one question can I just do this:
Code:
'--QDCOUNT
HeaderBytes(4) = 0
HeaderBytes(5) = 1
I get the feeling that wont work as I intend it to... I dont get how I can set a value of one across 2 bytes in any other way though (also, depending on how the byte array is ordered, couldnt that code be interpreted as 10 rather than 1?)
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
I found some C# code that does this same thing but I dont understand how it works and I dont want to just blindly follow it. Can you explain at all?
c#.net Code:
// the id of this message
data.Add((byte)0);
data.Add((byte)0);
// write the bitfields - _opCode is an Integer and _recursionDesired is a Boolean
data.Add((byte)(((byte)_opCode<<3) | (_recursionDesired?0x01:0)));
data.Add((byte)0);
// tell it how many questions
unchecked
{
data.Add((byte)(_questions.Count >> 8));
data.Add((byte)_questions.Count);
}
// etc etc, the other fields after this are just 0
From what I've read it looks like those >> and << are bit shifting operations. I'm still trying to get to grips with how to use those... but isnt this:
Code:
data.Add((byte)(_questions.Count >> 8));
the same as this:
because you are shifting every single set bit out of the byte by doing >> 8 arent you?
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
What's the data var?
If you have one byte, if you use the << 8 or the >> 8 (shif 8 bits), you have the original value...
And if you add to a byte another byte that has the value 0 you still got the same value...
10101010
+
00000000
-------------
10101010
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
the data variable in their example is just an ArrayList.
I dont quite get what you are saying though... This _questions.Count value is obviously an Integer, so when you say doing >> 8 will get "the original value" what do you mean?
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
I think its in this case easier to stay in unsigned integers. The calculations for setting values over 2 bytes becomes easier. So why not using an array of UShort's
For setting a bit (set to 1) just use:
OrgVar = OrgVar OR bitweight (1,2,4,8,etc)
For reading if a bit is set:
TestVar = OrgVar AND bitweight (1,2,4,8,etc)
Test if TestVar > 0
Bitshifter are handy for setting or reading bits in a loop. But in this case I think you will not need it.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Just to clear my point...
If you have One Byte (8 bits) shifthing 8 bits you will get the exact same value...
In the example, you have the count var, that's an integer (32bits) in .Net, so if you for shift right 8 bits it will be a different value...
Example:
0000 0000 0000 0000 0000 0001 0000 0000 = 512D
>> 8
0000 0000 0000 0000 0000 0000 0000 0001 = 1D
-----------
1000 0000 0000 0000 0000 0000 0000 0001 = 2 147 483 649D
>> 8
0000 0001 1000 0000 0000 0000 0000 0000 = 25 165 824D
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Oh right it loops back round does it? I thought if a bit went past the end of the bit boundary then it was lost.
OK thats fine then, but I am now more confused about this - if I have an Integer value then how am I storing it in a single Byte (as an Integer is 4 Bytes long) ?
God this is confusing! :(
Quote:
For setting a bit (set to 1) just use:
OrgVar = OrgVar OR bitweight (1,2,4,8,etc)
I think thats what I am doing in this line where I am trying to set the "RD" bit flag isnt it?
Code:
FirstParametersByte = CByte(FirstParametersByte Or (1 * 128))
Can anyone actually tell me if that code I posted in post #23 is right or wrong for what I am trying to do?
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Sorry - don't know C myself - but it sure looks like << and >> are bit shift operators.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
In this case bits 0 to 6 are reset and bit 7 is set:
Quote:
Dim FirstParametersByte As Byte = 0 FirstParametersByte = CByte(FirstParametersByte Or (1 * 128)) HeaderBytes(2) = FirstParametersByte
Quote:
What I am aiming for is for the RD bit in the second field (which I have posted in red font in the table above) to be set to 1, and the first field (the ID field) to be set to 5565 as this can apparently just be any 2 byte value. All other bits should be 0. Will that code I have got achieve that?
As far as I can see you are right.
Quote:
HeaderBytes(4) = 0
HeaderBytes(5) = 1
I think it must be the other way arround:
HeaderBytes(4) = 1
HeaderBytes(5) = 0
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
I wrote something wrong...
I thought that in VB.NET the bit shifting was circular, but it isn't... :(
Quote:
Originally Posted by MSDN
Arithmetic shifts are not circular, which means the bits shifted off one end of the result are not reintroduced at the other end. In an arithmetic right shift, the bits shifted beyond the rightmost bit position are discarded, and the leftmost (sign) bit is propagated into the bit positions vacated at the left. This means that if pattern has a negative value, the vacated positions are set to one; otherwise they are set to zero.
But it have a wired behavior because if you have a byte and if you shift by 8 bits you will get the exact same value, if you shift by 9 it's the same the shift by 1, that 8 shift that point me to the wrong direction...
About your question of the conversion of the Integer to Byte, i don't know how the C# handles the job, but if the number after the shifting can be saved in a byte there's no problem.
MSDN
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Another question, i'm a little lost...
What do you want to know from this word (2bytes)?
QR| Opcode |AA|TC|RD|RA| Z | RCODE
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Originally Posted by
mickey_pt
Another question, i'm a little lost...
What do you want to know from this word (2bytes)?
QR| Opcode |AA|TC|RD|RA| Z | RCODE
I dont want to read from it, I want to be able to set the RD bit and leave all the other bits set to 0, which I'm hoping is what my code in post 23 does..
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Code:
Dim FirstParametersByte As Byte = 0
FirstParametersByte = CByte(FirstParametersByte Or (1 * 128))
Why are you using CBYTE() here? Are you stepping through? What is the value of FirstParametersByte?
btw - it's dangerous when working these bits to use a bit-size datatype that is tight. It's better to use a bigger integer datatype so that arithmatic overflows don't burn you (this is my experience from mainframe coding in this area).
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Why are you using CBYTE() here? Are you stepping through? What is the value of FirstParametersByte?
You can see from that code you quoted what the value of FirstParametersByte is... its declared there and assigned 0 there. I'm using CByte because if I dont then it wont compile (Option Strict is on)
That FirstParametersByte is what I am using to create the first byte in this 2 byte part of the header:
Code:
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
because I want to set that RD field (which is 1 bit) and leave the rest of the bits as 0
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
You should use an INTEGER variable - it's got enough bits to work the entire 0 to 15 bit area.
Then convert that to whatever you need after - but at first you are doing simple bit manipulation that works well in an INTEGER variable
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
If you want to put the RD at 1 and everything else at 0...
Just put the first byte a 1 and the second a 0
HeaderBytes(2) = 1 (0000 0001)
HeaderBytes(3) = 0 (0000 0000)
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Originally Posted by
szlamany
You should use an INTEGER variable - it's got enough bits to work the entire 0 to 15 bit area.
Then convert that to whatever you need after - but at first you are doing simple bit manipulation that works well in an INTEGER variable
Huh? Why would I not use a Byte when I am working with bits and bytes :confused:
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
I thought you were trying to manage 0 to 15 bits - which is two bytes - a word.
But you don't care if the variable has more bits available.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Originally Posted by
mickey_pt
If you want to put the RD at 1 and everything else at 0...
Just put the first byte a 1 and the second a 0
HeaderBytes(2) = 1 (0000 0001)
HeaderBytes(3) = 0 (0000 0000)
but that wont be in the correct place will it? This is what I dont get, you guys are saying that the order of the bits (high to low vs low to high) doesnt make a difference as thats just how us humans like to view the bits - but in that header table it shows that single bits affect specific settings (in this case the RD setting) so surely I have to get them in the exact right place?
Lets use a different example bit, lets say I wanted to set the TC bit, how would I do that? Again its just 1 bit I want to set so are you saying I should just do the same and set HeaderBytes to 1? If so then how will the DNS server that receives these bytes know I meant the TC bit and not some other bit in that word?
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Originally Posted by
szlamany
I thought you were trying to manage 0 to 15 bits - which is two bytes - a word.
But you don't care if the variable has more bits available.
Well yeah I guess I am but I was under the impression that I had to deal with each 8 bit section (ie a Byte) on its own. This is getting more and more confusing.
So lets say I use an Integer in place of the Byte then (which I didnt realise I could do), once I have somehow set the relevant bits in there, how would I add that to my byte array? The end result has to be a Byte array as I need to send it via UDP
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
If you want to use a numeric data type use the Int16\Short (2bytes) that's a complete line of the header...
I think that your problem it's understanding the bits/bytes and how to read them...
My solution
Byte H(0) = 0000 0001 and Byte H(1) = 0000 0000
2Bytes = 0000 0001 0000 0000
The application that will read the header will read for example 2bytes (word) at once, so it will read all the line... so the value that you see like 1 will be 256 for the application. So everything it's related with the way that the data is read...
It's something like a string. You put:
H(0) = He
H(1) = llo
If you read the items separated you don't understand nothing, but if you read all the itens once you will see Hello.
I want to explain but my English isn't the best to explain... sorry...
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Well I tried sending my DNS query to a DNS server like so:
vb Code:
Dim HeaderBytes(11) As Byte
'--ID
HeaderBytes(0) = 1
HeaderBytes(1) = 1
'--Parameters
'First byte of parameter section
Dim FirstParametersByte As Byte = 0
FirstParametersByte = CByte(FirstParametersByte Or (1 * 128))
HeaderBytes(2) = FirstParametersByte
'Second byte of parameter section
HeaderBytes(3) = 0
'--QDCOUNT
HeaderBytes(4) = 1
HeaderBytes(5) = 0
'--ANCOUNT
HeaderBytes(6) = 0
HeaderBytes(7) = 0
'--NSCOUNT
HeaderBytes(8) = 0
HeaderBytes(9) = 0
'--ARCOUNT
HeaderBytes(10) = 0
HeaderBytes(11) = 0
'Build the question section
Dim DomainnameBytes() As Byte = System.Text.Encoding.ASCII.GetBytes("microsoft")
Dim DotComBytes() As Byte = System.Text.Encoding.ASCII.GetBytes("com")
Dim QuestionBytes(6 + DotComBytes.Length + DomainnameBytes.Length) As Byte
QuestionBytes(0) = CByte(DomainnameBytes.Length)
Array.Copy(DomainnameBytes, 0, QuestionBytes, 1, DomainnameBytes.Length)
QuestionBytes(1 + DomainnameBytes.Length) = CByte(DotComBytes.Length)
Array.Copy(DotComBytes, 0, QuestionBytes, 2 + DomainnameBytes.Length, DotComBytes.Length)
QuestionBytes(QuestionBytes.Length - 5) = 0
QuestionBytes(QuestionBytes.Length - 4) = 0
QuestionBytes(QuestionBytes.Length - 3) = 15
QuestionBytes(QuestionBytes.Length - 2) = 0
QuestionBytes(QuestionBytes.Length - 1) = 1
'Combine the header and question
Dim FinalBytes((QuestionBytes.Length + HeaderBytes.Length) - 1) As Byte
Array.Copy(HeaderBytes, 0, FinalBytes, 0, HeaderBytes.Length)
Array.Copy(QuestionBytes, 0, FinalBytes, HeaderBytes.Length, QuestionBytes.Length)
Dim DNSServer As New IPEndPoint(IPAddress.Parse("192.168.0.254"), 53)
Dim sock As New Net.Sockets.Socket(Net.Sockets.AddressFamily.InterNetwork, Net.Sockets.SocketType.Dgram, Net.Sockets.ProtocolType.Udp)
'Send the data
sock.SendTo(FinalBytes, 0, FinalBytes.Length, Net.Sockets.SocketFlags.None, DNSServer)
'Receive the response
Dim ReceivedBytes(512) As Byte
Dim BytesRead As Integer = sock.Receive(ReceivedBytes, ReceivedBytes.Length, Sockets.SocketFlags.None)
and the server just did not respond at all. So I tried your suggestion Mickey and changed it to this:
vb Code:
'--Parameters
'First byte of parameter section
HeaderBytes(2) = 1
'Second byte of parameter section
HeaderBytes(3) = 0
and now the server responds :) but not with what I was expecting :( lol
It just sends back 12 bytes, all 0 apart from the first and second Bytes are the same as my ID that I set (in this case 1 and 1) and the third and fourth Bytes are both 129. The response that the server sends back starts with that same header format that I have been working with, so I have to somehow figure out what 129 129 means when applied to the fields that are in those 2 bytes...
Code:
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
EDIT: I changed the order of the 4th and 5th bytes as someone suggested in an earlier post and now I get a 78 byte response :) which I thought was still not quite right because I am comparing my byte response (converted to hex) to the response shown here (about half way down the page): http://www.codeproject.com/KB/IP/dnslookupdotnet.aspx
But I just noticed that when I actually do an NSLOOKUP for microsoft.com's MX records now it does only bring back one result rather than the 3 that it brought up when that article was written... so maybe its working properly now :) I'm going to have to properly understand it though because I need to be able to work with the response it has sent me! I'm going out for the weekend now but I'll pick this up again next week, thanks for all the help so far guys
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Hi here is "someone again".
Quote:
so I have to somehow figure out what 129 129 means when applied to the fields that are in those 2 bytes...
129 has a bit patern of: 10000001.
So the first byte will say:
Bit QR is set and RD is set. QR will say a response and that is correct. Not sure why you want bit RD set. The RFC mentioned "Recursive query support is optional."
The second byte:
RA is set which means that recursion is available and RCODE=8 which is strange.
Be careful with comparing the HEX codes. With the table presented LSB is on the left and normaly in a HEX viewer LSB is on the right.
Sorry for my english. Have some problems to put in right in english.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
The RFC mentioned "Recursive query support is optional."
yes its an option that I want to use...
Basically if you dont tell a DNS query to be 'recursive' then the DNS server you send the query to will not pass that request on to any further DNS servers if it does not know the answer... so in 99% of cases you want the DNS query to be recursive.
Anyway :) if you read my post after that you will see that I no longer get that 129 129 response, I now get a 'proper' response from the server so I just need to work on reading that response. I might not get chance to do that for another couple of days now though :( but I will post back here if I have problems (which I undoubtedly will...)
Thanks
Chris
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
I know no one here has mentioned this so maybe its not the best way to do things but I had another look at the BitArray class last night and it seems very useful for what I am wanting to do. You can simply create a new instance of it and set the length, then set each item inside it to True or False to represent the bit being set or not set. Then when you are done you just copy it to a Byte array and there you go, all of the bits you wanted to set are set :) Same for reading a byte array as bits, you can pass in a byte array to the constructor of the BitArray class and then just loop through the bits and see what they are all set to - its much easier than messing about with bit masks and all that.
Having said that, I'm glad I read all of the things you guys have said in this thread as its given me a much better understanding of bits and bytes (which came in handy the other day actually when doing some networking work).
I'll post an example of how I'm using this BitArray later today :)
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
It's the best way as long as it's easy for you to construct and maintain and also doesn't slow things down.
If you are processing lots of this stuff at a fast pace then the "old tried and true" method might serve you better.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Yeah you are probably right, I will try and get the hang of the AND and OR stuff for the final version of the app but first I just want to actually send a query to the DNS server and parse the response into something meaningful :)
I'm actually starting to wonder if this table is showing the bits in the wrong order...
Code:
The header contains the following fields:
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
For several reasons.
1. Every other example of bits on the web seems to do it the other way round, ie most significant bit first
2. When I tried to set the RD bit by setting that byte to 128, the server does not respond at all. So perhaps I am actually setting the first bit (bit 0) whcih is the QR bit. The QR flag is the bit that specifies whether or not this is a query or a response, and by setting it to 1 I would be indicating that this is a response so of course the server wont reply as it doesnt think it has received a question. When I change that byte to 1 instead of 128 then the server responds.
3. In the server response, I get the following bytes (as well as much more afterwards):
1, 1, 129, 128.
The two 1s are my ID. The 129 and 128 are the 2 bytes that relate to those parameter fields and 129 would mean bit 0 (QR) and bit 7 (RD) are set so thats fine, but 128 would mean the RCODE nibble is just set to a value of 1 - the RCODE nibble being set to 1 means the following:
Quote:
Format error - The name server was
unable to interpret the query.
so maybe my request is incorrect but if that was the case then I wouldnt have thought I would then get another 70 bytes of data after that. So if my theory about the bits being the other way round (the normal way) is correct then what that actually means is that the RCODE nibble is set to 0 which is what I would expect, and its actually the RA bit flag that is set, which simply means that recursion is available and apparently is only set in a response.
4. If I change my request to use an invalid domain name, (microsoft.co instead of microsoft.com) then I get 129, 131 for the parameter fields, which would mean again the QR and RD bit flags are set which is fine, but then it would mean the RA bit flag is set and the 3 bit Z field is set to something but the RFC states that the Z field should always be 0 as it is reserved for future use. If we turn it round and look at it as if the bits are the 'normal' way round then it would equate to the RA bit flag being set which is fine, and it would mean the Z field is 0 and the RCODE nibble is set to 3 which means:
Quote:
3 Name Error - Meaningful only for
responses from an authoritative name
server, this code signifies that the
domain name referenced in the query does
not exist.
So maybe even though they have labeled the bits from 0 to 15, this doesnt actually mean they are talking about the bits in the opposite order to how everyone else seems to talk about bits... what do you think?
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
OK after some more testing I am quite convinced now that the bits in that table are labelled in an 'odd' way and that to be easier to follow the table should actually look more like this:
Code:
The header contains the following fields:
1 1 1 1 1 1
7 6 5 4 3 2 1 0 5 4 3 2 1 0 9 8
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
and I think I'm starting to get the hang of using AND, OR and AND NOT now as well :) Here is how I am setting the AA bit and the RD bit in that second field:
vb.net Code:
'--Parameters
HeaderBytes(2) = (1 Or 4) 'Sets the RD bit flag and AA flag
HeaderBytes(3) = 0
and then when I want to check to see if the QR bit flag is set I am doing this:
vb.net Code:
If (ReceivedBytes(2) And 128) = 128 Then
'QR flag is set
End If
is that the right way to be doing it?
Thanks
Chris
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Yes - this is good code
HeaderBytes(2) = (1 Or 4)
And I see that those are the bit locations - RD is bit 0 and AA is bit 2 (which are values of 1 and 4)
This code can be written three ways
If (ReceivedBytes(2) And 128) = 128 Then
If (ReceivedBytes(2) And 128) <> 0 Then
If ReceivedBytes(2) And 128 Then
I prefer the last method myself - no reason to add the = 128 or <> 0 stuff.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Ah I see, thanks for that tip - with Option Strict on though I have to do the following:
vb Code:
If CBool(ReceivedBytes(2) And 128) Then
but I still prefer that over the way I was doing it :)
So one thing I am still a bit puzzled about (it may just be the terminology) is bit shifting. If I can test for any individual bit being set by just using AND then why/when would I use bit shifting? Is that more for when you want to set a bit rather than just checking to see if a bit is set?
Thanks
Chris
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
I hope ALL of you are aware that you have just provided a college semester's worth of education for thos of us who can't afford to go to college (and are too old, and gotta work, and discovered programming as a "hobby" late in the game, etc . . .).
This string (EDIT: THis THREAD-too much code happening!)should be moved to the code bank, or a faq or something. I could not have found a better explanation of binary operations(?) by searching.
It will be a while before I actually need to USE this, and even longer before I get my head around it, but wow! Very cool stuff.
Thanks!
ps: One persons profession is another person's hobby is another's twisted obsession!
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
haha I'm glad my plethora of questions as I struggle to grasp this stuff might prove to be helpful to others :)
and in response to your PS - this is just my hobby :)
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Originally Posted by
chris128
So one thing I am still a bit puzzled about (it may just be the terminology) is bit shifting. If I can test for any individual bit being set by just using AND then why/when would I use bit shifting? Is that more for when you want to set a bit rather than just checking to see if a bit is set?
That OPCODE is 4 bits - right? That means it's a value from 0000 (0) to 1111 (15).
If you want to extract that value - and it's in the BYTE - you need to shift it down to position 0 and also MASK it to hide other bits that shift down with it.
So once again - the byte with the opcode - let's say it:
1101 0111
The 1010 bits is the 10 values I want to extract. The decimal value of 1101 0111 is not 10 [edit - oops] - so first thing is to shift it down
1101 0111 / 8
0001 1010 - now the 1010 is in bit 0, bit 1, bit 2 and bit 3
0000 1111 - this is the 15 mask
AND these and you get
0000 1010 - this is the 10 I want - it's in a byte - but the value of 10 (from the opcode) came through.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Ahh yeah I see, I hadnt considered checking anything other than individual bit flags :)
This brings me on to another question actually... (I know, will they ever end?)
For the fields that are 2 full bytes (ID, QDCOUNT etc) is there any way I can set them using the UInt16 type? Well, I know there is as UInt16 is just 2 bytes, but I just cant figure out how to get this to work with my byte array. The ID for example is bytes 0 and 1 in my byte array, and I would like a way to set both of these bytes in one go when given a UInt16 value - is that possible or do I have to break the UInt16 value down into 2 bytes and set byte 0 and byte 1 separately?
EDIT: and also :) am I using And Not in the correct way here? I just want it to clear a specific bit and leave all other bits as they are
vb.net Code:
Private _QR As Boolean
Public Property QR() As Boolean
Get
Return _QR
End Get
Set(ByVal value As Boolean)
If value = True Then
_HeaderBytes(2) = CByte((HeaderBytes(2) Or 128))
Else
_HeaderBytes(2) = CByte((HeaderBytes(2) And Not 128))
End If
_QR = value
End Set
End Property
As you can tell, I am going to have a property that relates to each of this configurable bit flags so when someone sets the property I want it to be reflected in the Byte array :)
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
You must shift before you OR - that's all.
Take you 2-bit value - doesn't matter if it's in a word, longword, quadword - it's in bits 0 and 1 - that's all.
SHIFT it up to where you want it to go with *2 or *4 or *8...
then set it with OR - you aren't OR's the "value" you think you want to because you shifted it - but where you shift it to is the 2 bits that it has to be.
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
I dont get why I have to shift before I do an OR because it seems to work without doing that..
For example if I want to set bits 3 and 4 (00011000) I can do this and it sets the correct bits:
vb Code:
HeaderBytes(2) = (HeaderBytes(2) OR 8 OR 16)
or is it just that I am doing the shifting mentally (e.g I'm working out that I would need to set 8 and 16 to set those bits) rather than using the code to just shift whatever value I want into whatever spot I want?
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
Originally Posted by
chris128
...or is it just that I am doing the shifting mentally (e.g I'm working out that I would need to set 8 and 16 to set those bits) rather than using the code to just shift whatever value I want into whatever spot I want?
By Jove - I think he's got it.
Yes - that's exactly it!
If you are "extracting" the value you have no idea what it is - so shifting is needed.
If you shift out - then you shift in to put a value.
We should digress into a couple of posts about SI and SO (character 15 and 16? Ctrl/O and Ctrl/N? Is that right?)
-
Re: Bits, Bytes and Boomerangs (without the boomerangs...)
Quote:
We should digress into a couple of posts about SI and SO (character 15 and 16? Ctrl/O and Ctrl/N? Is that right?)
I have no idea what you are talking about lol