我需要将Mac地址转换为IPv6 Link本地地址。
link-local IPv6是从NIC’s mac地址推断出来的。
转换过程如下。


使用mac地址:例如52:74:f2:b1:a8:7f
将ff:fe放在中间:52:74:f2:ff:fe:b1:a8:7f
重新格式化为IPv6表示法5274:f2ff:feb1:a87f
将第一个八位位组从十六进制转换为二进制:52 -> 01010010
反转索引6的位(从0开始计数):01010010 -> 01010000
将八位位组转换回十六进制:01010000 -> 50
用新计算的第一个八位位组代替:5074:f2ff:feb1:a87f
在链接本地前缀之前:fe80::5074:f2ff:feb1:a87f


这似乎是许多数字系统之间特定的字符串操作和转换。
我一直在寻找Java中的实用程序类,该实用程序类可以帮助我以更有效的方式进行操作。
我看到Java在InetAddress中有方法来确定所讨论的地址是否是本地链接。

最佳答案

我尝试使用StringBuilder实现用于字符串操作的自定义生成器。希望对您有帮助。

习俗课

public class Address  {
    @SuppressWarnings("unused")
    private static final long serialVersionUID = 1L;
    String ip;

    Address(String ip) {
        this.ip = ip;
    }

    boolean isLinkLocal() throws UnknownHostException{
        return getInet6Address().isLinkLocalAddress();
    }

    @SuppressWarnings("static-access")
    Inet6Address getInet6Address() throws UnknownHostException {
        return (Inet6Address) Inet6Address.getByName(getIp());
    }

    String getIp() {
        return this.ip;
    }
}


建造者

public class AddressBuilder {
    private String mac1;
    private String mac2;
    private String mac3;
    private String mac4;
    private String mac5;
    private String mac6;
    private String ipv6;
    private static final String IPV6_1 = "FE80::";
    private static final String FF_FE = "FF:FE";
    private static final String DOTS = ":";
    /**
     * Constructor
     */
    public AddressBuilder () { }
    /**
     * setMac
     *
     * @param mac
     * @return
     */
    private static final String LOG_MESSAGE_1 =
            "MAC set to : {%s,%s,%s,%s,%s}";
    public AddressBuilder setMac(String mac){
        String[] splittedMac = mac.split(":");
        this.mac1 = splittedMac[0];
        this.mac2 = splittedMac[1];
        this.mac3 = splittedMac[2];
        this.mac4 = splittedMac[3];
        this.mac5 = splittedMac[4];
        this.mac6 = splittedMac[5];
        log(LOG_MESSAGE_1, splittedMac);
        return this;
    }
    /**
     * throwFffeAndReformatToIPv6Notation
     *
     * @return
     */
    private static final String LOG_MESSAGE_2 =
            "Throwing FFFE and reformat to IPV6 notation : %s";
    public AddressBuilder throwFffeAndReformatToIPv6Notation() {
        StringBuilder sb = new StringBuilder();
        this.ipv6 = sb
            .append(mac1)
            .append(mac2)
            .append(DOTS)
            .append(mac3)
            .append(FF_FE)
            .append(mac4)
            .append(DOTS)
            .append(mac5)
            .append(mac6)
            .toString();
        log(LOG_MESSAGE_2, this.ipv6);
        return this;
    }
    /**
     * convertFirstOctetFromHexToBinaryAndReplaceIt
     *
     * @return
     */
    private static final String LOG_MESSAGE_3 =
            "Convert 1st octet from hex to binary : %s -> %s";
    private static final String LOG_MESSAGE_4 =
            "Invert bit at 6th index : %s";
    private static final String LOG_MESSAGE_5 =
            "Convert this binary string to hex : %s";
    private static final String LOG_MESSAGE_6 =
            "Replace octet with the newly calculated one : %s";
    public AddressBuilder convertFirstOctetFromHexToBinaryAndReplaceIt() {
        String firstOctet = this.ipv6.substring(0, 2);
        String binaryString = new BigInteger(firstOctet, 16).toString(2);
        log(LOG_MESSAGE_3, firstOctet, binaryString);
        char[] binaryCharArray = binaryString.toCharArray();
        binaryCharArray[6] = Integer
            .parseInt(Character.toString(binaryString.toCharArray()[6])) == 0
                ? '1' : '0';
        binaryString = new String(binaryCharArray);
        log(LOG_MESSAGE_4, binaryString);
        String hex1stOctet = new BigInteger(binaryString, 2).toString(16);
        log(LOG_MESSAGE_5, hex1stOctet);
        this.ipv6 = hex1stOctet+this.ipv6.substring(2);
        log(LOG_MESSAGE_6, this.ipv6);
        return this;
    }
    /**
     *
     * prependLocalLinkPrefix
     *
     * @return
     */
    private static final String LOG_MESSAGE_7 =
            "Prepend link local prefix : %s";
    AddressBuilder prependLocalLinkPrefix() {
        this.ipv6 = (IPV6_1+this.ipv6).toUpperCase();
        log(LOG_MESSAGE_7, this.ipv6);
        return this;
    }
    /**
     * build
     *
     * @return
     */
    Address build() {
        return new Address(this.ipv6);
    }
    /**
     * log
     *
     * @param message
     * @param strings
     */
    private static void log(String message, String ...strings) {
        System.out.println(String.format(message, strings));
    }
}


使用例

public class App {
    public static void main(String[] args) {
        String mac = "CC:BE:59:B3:97:03";
        AddressBuilder ad = new AddressBuilder();
        Address address = ad
            .setMac(mac)
            .throwFffeAndReformatToIPv6Notation()
            .convertFirstOctetFromHexToBinaryAndReplaceIt()
            .prependLocalLinkPrefix()
            .build();
        try {
            System.out.println("is Link local? "+address.isLinkLocal());
            System.out.println("link local : "+address.getIp());
        } catch (UnknownHostException uhe) {
            System.out.println("is Link local? no");
        }
    }
}


输出量

MAC设置为:{CC,BE,59,B3,97}
抛出FFFE并重新格式化为IPV6表示法:CCBE:59FF:FEB3:9703
将第一个八位位组从十六进制转换为二进制:CC-> 11001100
第六索引的反转位:11001110
将此二进制字符串转换为十六进制:ce
用新计算的八位位组替换八位位组:ceBE:59FF:FEB3:9703
前缀链接本地前缀:FE80 :: CEBE:59FF:FEB3:9703
Link是本地的吗?真正
本地链接:FE80 :: CEBE:59FF:FEB3:9703

关于java - 将Mac地址转换为Java中的本地IPv6链接,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56132467/

10-12 01:23
查看更多