【Web前端问题】关于 java 位运算

这段代码中和0x0ff与运算是什么意思? 获取length的原理是什么?
其中对象in如下

请输入图片描述

// read and check header

int type = in.read() & 0x0ff;

int identifier = in.read() & 0x0ff;

int length = (in.read() & 0x0ff) << 8 | (in.read() & 0x0ff);

所有的代码

/**

    • Reads a Radius packet from the given input stream and

    • creates an appropiate RadiusPacket descendant object.

    • Reads in all attributes and returns the object.

    • Decodes the encrypted fields and attributes of the packet.

    • @param dictionary dictionary to use for attributes

    • @param sharedSecret shared secret to be used to decode this packet

    • @param request Radius request packet if this is a response packet to be

    • decoded, null if this is a request packet to be decoded

    • @return new RadiusPacket object

    • @exception IOException if an IO error occurred

    • @exception RadiusException if the Radius packet is malformed
      */

    1. static RadiusPacket decodePacket(Dictionary dictionary, InputStream in, String sharedSecret, RadiusPacket request)

    2. IOException, RadiusException {

         // check shared secret

      if (sharedSecret == null || sharedSecret.length() == 0)

      throw new RuntimeException("no shared secret has been set");

      // check request authenticator

      if (request != null && request.getAuthenticator() == null)

      throw new RuntimeException("request authenticator not set");

      // read and check header

      int type = in.read() & 0x0ff;

      int identifier = in.read() & 0x0ff;

      int length = (in.read() & 0x0ff) << 8 | (in.read() & 0x0ff);

      if (request != null && request.getPacketIdentifier() != identifier)

      throw new RadiusException("bad packet: invalid packet identifier (request: " + request.getPacketIdentifier() + ", response: " + identifier);

      if (length < RADIUS_HEADER_LENGTH)

      throw new RadiusException("bad packet: packet too short (" + length + " bytes)");

      if (length > MAX_PACKET_LENGTH)

      throw new RadiusException("bad packet: packet too long (" + length + " bytes)");

      // read rest of packet

      byte[] authenticator = new byte[16];

      byte[] attributeData = new byte[length - RADIUS_HEADER_LENGTH];

      in.read(authenticator);

      in.read(attributeData);

      // check and count attributes

      int pos = 0;

      int attributeCount = 0;

      while (pos < attributeData.length) {

      if (pos + 1 >= attributeData.length)

      throw new RadiusException("bad packet: attribute length mismatch");

      int attributeLength = attributeData[pos + 1] & 0x0ff;

      if (attributeLength < 2)

      throw new RadiusException("bad packet: invalid attribute length");

      pos += attributeLength;

      attributeCount++;

      }

      if (pos != attributeData.length)

      throw new RadiusException("bad packet: attribute length mismatch");

      // create RadiusPacket object; set properties

      RadiusPacket rp = createRadiusPacket(type);

      rp.setPacketType(type);

      rp.setPacketIdentifier(identifier);

      rp.authenticator = authenticator;

      // load attributes

      pos = 0;

      while (pos < attributeData.length) {

      int attributeType = attributeData[pos] & 0x0ff;

      int attributeLength = attributeData[pos + 1] & 0x0ff;

      RadiusAttribute a = RadiusAttribute.createRadiusAttribute(dictionary, -1, attributeType);

      a.readAttribute(attributeData, pos, attributeLength);

      rp.addAttribute(a);

      pos += attributeLength;

      }

      // request packet?

      if (request == null) {

      // decode attributes

      rp.decodeRequestAttributes(sharedSecret);

      rp.checkRequestAuthenticator(sharedSecret, length, attributeData);

      } else {

      // response packet: check authenticator

      rp.checkResponseAuthenticator(sharedSecret, length, attributeData, request.getAuthenticator());

      }

      return rp;

      }

    回答:

    0x0ff 就是

    0000 0000 1111 1111

    一个数字和 0x0ff 进行与运算,则会把高8位置0,低8位保留。


    回到你的程序中,通过这个函数猜测应该是解析的 RFC2866 报文:

    报文格式:

     0                   1                   2                   3

    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    | Code | Identifier | Length |

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    | |

    | Authenticator |

    | |

    | |

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

    | Attributes ...

    +-+-+-+-+-+-+-+-+-+-+-+-+-

    根据格式, 0-7位是 CODE 信息,在你的函数中用 type 存储。(注意 type 的类型,是 int)

    @brayden 提到了,InputStream.read() 一个读一个 byte,正好是 8 位,所以,如果写 byte type = in.read() 就正好了。但是 type 的类型是 int,因此我们需要处理一下。

    如果我们读入的是 5,那么当我们把他转换成 int 时,也应该是 5。那么需要在前面添加 0。

                0000 0101

    & 0000 0000 1111 1111

    -------------------------------

    0000 0000 0000 0101

    同理,读报文的 8-15位。

    length 的值比较难读取,因为它一共16位,而 in.read() 每次只能读8个字节,那么就需要读取两次,然后拼凑。方法是,先读8位,然后左移,再读8位。

    int length = (in.read() & 0x0ff) << 8 | (in.read() & 0x0ff);

    回答:

    java里InputStream.read()一个读一个byte, 但是返回一个int, 四字节; 但实际上有用的只是最后的那个byte. 所以需要每次in.read() & 0x0ff;

    具体到这段代码,

    读第一个byte到一个int型, 赋值给type;

    读第二个byte到一个int型, 赋值给identifier;

    读第三个byte, 第四个byte, 第三个字节左移8位, 和第四个字节拼接起来, 赋值给length.

    以上是 【Web前端问题】关于 java 位运算 的全部内容, 来源链接: utcz.com/a/143516.html

    回到顶部