问题
The following is from the book C# Network Programmingm by Richard Blum:
public byte[] get(string request, string host, string community, string_ mibstring)
{
byte[] packet = new byte[1024];
byte[] mib = new byte[1024];
int snmplen;
int comlen = community.Length;
string[] mibvals = mibstring.Split('.');
int miblen = mibvals.Length;
int cnt = 0, temp, i;
int orgmiblen = miblen;
int pos = 0;
// Convert the string MIB into a byte array of integer values
// Unfortunately, values over 128 require multiple bytes
// which also increases the MIB length
for (i = 0; i < orgmiblen; i++)
{
temp = Convert.ToInt16(mibvals[i]);
if (temp > 127)
{
mib[cnt] = Convert.ToByte(128 + (temp / 128));
mib[cnt + 1] = Convert.ToByte(temp - ((temp / 128) * 128));
cnt += 2;
miblen++;
}
else
{
mib[cnt] = Convert.ToByte(temp);
cnt++;
}
}
snmplen = 29 + comlen + miblen - 1; //Length of entire SNMP packet
//The SNMP sequence start
packet[pos++] = 0x30; //Sequence start
packet[pos++] = Convert.ToByte(snmplen - 2); //sequence size
//SNMP version
packet[pos++] = 0x02; //Integer type
packet[pos++] = 0x01; //length
packet[pos++] = 0x00; //SNMP version 1
//Community name
packet[pos++] = 0x04; // String type
packet[pos++] = Convert.ToByte(comlen); //length
//Convert community name to byte array
byte[] data = Encoding.ASCII.GetBytes(community);
for (i = 0; i < data.Length; i++)
{
packet[pos++] = data[i];
}
}
I didn't understand the following code:
for (i = 0; i < orgmiblen; i++)
{
temp = Convert.ToInt16(mibvals[i]);
if (temp > 127)
{
mib[cnt] = Convert.ToByte(128 + (temp / 128));
mib[cnt + 1] = Convert.ToByte(temp - ((temp / 128) * 128));
cnt += 2;
miblen++;
}
else
{
mib[cnt] = Convert.ToByte(temp);
cnt++;
}
}
I do understand this is for putting down into two bytes if the temp is larger then one byte. But what is the calculation being done 128+(temp/128) and then for the second byte: temp- (temp/128)*128, this is what i don't understand.
Please help, Thank you.
回答1:
Below is quoted from Understanding SNMP MIBs page 394, as this book describes the technical details better than any others,
An encoded OBJECT IDENTIFIER consists of each sub-identifier in the original value encoded and concatenated. Each sub-identifier is encoded as a series of octets, which is as follows,
- Bit 8 in each octet indicates if it is the last octet of the sub-identifier by setting this bit to 0
- Bits 7 through 1 in the octets, when concatenated, form the value of the sub-identifier
- The first octet in the sub-identifier may not have the value 80 (in HEX). This ensures that the smallest number of octets are used for the encoding. A value of 80 (in HEX) would indicate that more octets follow, but the value bits (7-1) are set to zero.
The pasted source code in the question body in fact follows the rules to parse the bytes. Thus, if you understand the rules, you can understand the code.
(Updated: The rules come from ITU-T X.690, ISO/IEC 8825-1.)
回答2:
if temp is larger than 127, then it will be split across 2 bytes. lets look at 2 examples/
temp = 100;
128 + (temp / 128); //(temp / 128) = 0 + 128 so the mib[cnt] is set to 128
temp - ((temp/128) * 128); // 0*128 = 0. subtracted from temp leaves the original. so you end up with
mib[cnt] = 128;
mib[cnt+1] = 100;
Now if temp is > 127
temp = 200;
128 + (temp / 128); //(temp / 128) = 1 + 128 so the mib[cnt] is set to 129
temp - ((temp/128) * 128); // 1*128 = 128. 200-128 = 72. so you end up with
mib[cnt] = 129;
mib[cnt+1] = 72;
So basically, it's taking a number, testing if it's > 7 bytes (-128 => +127 is one signed byte) and if the number you've supplied would overflow that range, it converts it into a 2 byte value/
回答3:
This works with all values:
for (i = 0; i < orgmiblen; i++)
{
temp = Convert.ToInt64(mibvals[i]);
int k = (int)Math.Log((Double)temp, (Double)2) / 7;
miblen += k;
int continuation = 0;
do
{
mib[cnt++ + k] = Convert.ToByte((temp & 127) + continuation);
temp = ((int)(temp / 128));
continuation = 128;
k -= 2;
}
while (temp > 0);
}
来源:https://stackoverflow.com/questions/17270451/strange-snmp-shifting-operation