将字节解码为ipaddress

时间:2016-02-02 11:38:01

标签: java bytearray

我有一个java应用程序,它监听套接字上的upd数据包。我发送原始字节然后转换为IP地址。数据包由9个字节组成。 4表示第一个地址,然后1表示掩码,另外4个字节表示第二个地址。

发生的奇怪事情是2地址的2字节打印错误的值。为什么呢?

package net.floodlightcontroller.openlisp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

import net.floodlightcontroller.packet.IPv4;

public class UdpServerCp extends Thread {

    protected OFLISPRules oflr = OFLISPRules.getInstance();
    private static UdpServerCp instance;
    private int priority = 3;

    public static synchronized UdpServerCp getInstance() {
        if (instance == null)
        instance = new UdpServerCp();
        return instance;
    }

    public void run() {

        OpenlispHandler oh = OpenlispHandler.getInstance();

        byte[] receiveData = new byte[9];
        DatagramPacket receivePacket;
        System.out.println("Waiting to receive...");
        DatagramSocket serverSocket;
        try {
            serverSocket = new DatagramSocket(8888);

            while (true) {
                receivePacket = new DatagramPacket(receiveData, receiveData.length);

                serverSocket.receive(receivePacket);

                // if i receive a packet and it doesn't already have a flow rule
                // process it
                if ((receivePacket != null) && (oh.isNewOFRuleAdded() == false)){
                    byte[] bytes = receivePacket.getData();


                    //int eidInteger = ((int)bytes[3] << 8*3) + ((int)bytes[2] << 8*2) + ((int)bytes[1] << 8) + ((int) bytes[0]);
                    int eidInteger = ((int)bytes[0] << 8*3) + ((int)bytes[1] << 8*2) + ((int)bytes[2] << 8) + ((int) bytes[3]);
                    String eidAddressString = InetAddress.getByAddress(unpack(eidInteger)).getHostAddress();
                    System.out.println("buffer EID: " + eidAddressString);

                    int prefixInteger = (int) bytes[4];
                    System.out.println("buffer PREFIX: " + prefixInteger);

                    int rlocInteger = ((int)bytes[5] << 8*3) + ((int)bytes[6] << 8*2) + ((int)bytes[7] << 8) + ((int) bytes[8]);
                    String rlocAddressString = InetAddress.getByAddress(unpack(rlocInteger)).getHostAddress();
                    System.out.println("buffer RLOC: " + rlocAddressString);



                    IPv4 eidADD = new IPv4();
                    IPv4 rlocADD = new IPv4();
                    eidADD.setDestinationAddress(eidAddressString);
                    rlocADD.setDestinationAddress(rlocAddressString);

                    oflr.rlocOFRule(eidADD, prefixInteger, rlocADD, priority);
                    oh.setNewOFRuleAdded(true);
                    this.priority++;
                }
            }
        } catch (SocketException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    byte[] unpack(int bytes) {
        return new byte[] { 
                (byte) ((bytes >>> 24) & 0xff),
                (byte) ((bytes >>> 16) & 0xff), 
                (byte) ((bytes >>> 8) & 0xff), 
                (byte) ((bytes) & 0xff) };
    }
}

2 个答案:

答案 0 :(得分:2)

当您将一个字节转换为int时,您可能会得到负数。由于218是负字节值,因此会发生这种情况并导致前一个字节递减。

int rlocInteger = ((int)bytes[5] << 8*3) + ((int)bytes[6] << 8*2) + ((int)bytes[7] << 8) + ((int) bytes[8]);

要解决此问题,请使用0xff进行掩码,例如:((bytes[5]&0xff) << 8*3)

答案 1 :(得分:0)

我认为没有理由通过一个整数从9字节数组中获取4个字节,只需复制你需要的子数组。类似的东西:

byte[] bytes = receivePacket.getData();
String eidAddressString = InetAddress.getByAddress(Arrays.copyOfRange(bytes, 0, 4)).getHostAddress();
System.out.println("buffer EID: " + eidAddressString);

int prefixInteger = (int) bytes[4];
System.out.println("buffer PREFIX: " + prefixInteger);

String rlocAddressString = InetAddress.getByAddress(Arrays.copyOfRange(bytes, 5, 9)).getHostAddress();
System.out.println("buffer RLOC: " + rlocAddressString);