奇怪的SNMP移位操作

时间:2013-06-24 07:50:13

标签: c# .net snmp

以下内容来自Richard Blum的C#Network Programmingm一书:

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];
    }
}

我不明白以下代码:

    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++;
        }
    }

我知道如果temp大于一个字节,则将其放入两个字节。但是计算结果是128+(temp / 128)然后是第二个字节:temp-(temp / 128)* 128,这是我不明白的。

请帮助,谢谢。

3 个答案:

答案 0 :(得分:3)

如果temp大于127,则它将被分割为2个字节。让我们来看看2个例子/

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;

现在,如果temp是&gt; 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;

所以基本上,这是一个数字,测试它是否&gt; 7个字节(-128 =&gt; +127是一个有符号字节),如果你提供的数字会溢出该范围,它会将其转换为2字节值/

答案 1 :(得分:1)

下面引用了了解SNMP MIB 第394页,因为本书比其他任何内容更好地描述了技术细节,

  

编码的OBJECT IDENTIFIER由编码和连接的原始值中的每个子标识符组成。每个子标识符被编码为一系列八位字节,如下所示,

     
      
  • 每个八位字节中的位8通过将此位设置为0来指示它是否是子标识符的最后一个八位字节
  •   
  • 八位字节中的第7位到第1位,当连接时,形成子标识符的值
  •   
  • 子标识符中的第一个八位字节可能不具有值80(在HEX中)。这确保了最小数量的八位字节用于编码。值80(以十六进制表示)表示后面有更多八位字节,但值位(7-1)设置为零。
  •   

问题体中的粘贴源代码实际上遵循解析字节的规则。因此,如果您了解规则,则可以理解代码。

(更新:规则来自ITU-T X.690, ISO/IEC 8825-1。)

答案 2 :(得分:-1)

这适用于所有值:

        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);
        }