Java将IP +端口转换为长和后

时间:2016-10-19 14:12:09

标签: java bit-manipulation

我试图将一个ipaddress和端口存储在Long中。我的代码适用于值小于255的端口,但不能再用于其他任何端口。

import java.util.*;
import java.lang.*;
import java.io.*;

class Test {

    public static void main(String[] args) {
        String first = "192.168.1.2:84";
        String second = "255.255.255.255:65535";

        long ip1 = ipToLong(first);
        System.out.println("iptoLong  : " + ip1);

        System.out.println("longToIp  : " + longToIp(ip1));

        System.out.println();

        ip1 = ipToLong(second);
        System.out.println("iptoLong  : " + ip1);

        System.out.println("longToIp  : " + longToIp(ip1));

    }

    public static long ipToLong(String ipAddress) {
        int port = Integer.parseInt(ipAddress.substring(ipAddress.indexOf(":") + 1, ipAddress.length()));
        ipAddress = ipAddress.replace(":", "").replace(""+port, "");

        String[] ip = ipAddress.split("\\.");

        long result = 0;
        result |= Long.parseLong(ip[0]) << 40;
        result |= Long.parseLong(ip[1]) << 32;
        result |= Long.parseLong(ip[2]) << 24;
        result |= Long.parseLong(ip[3]) << 16;

        result |= port << 8;
        result |= port;

        return result;
    }

    public static String longToIp(long i) {
        long port  = ((i >> 8) & 0xFF) | (i & 0xFF);

        return ((i >> 40) & 0xFF) +
                   "." + ((i >> 32) & 0xFF) +
                   "." + ((i >> 24) & 0xFF) +
                   "." + ((i >> 16) & 0xFF) +
                   ":" + port;

    }
}

以下是该代码输出的内容:

iptoLong  : 211827803968596
longToIp  : 192.168.1.2:84

iptoLong  : 281474976710655
longToIp  : 255.255.255.255:255

正如您在第二个示例中所看到的,它打印255而不是65535。

以下是指向代码段的ideone链接:http://ideone.com/rWo7qJ

谢谢!

2 个答案:

答案 0 :(得分:2)

你的端口编码和解码都是错误的。

对于您正在进行的编码:

result |= port << 8;
result |= port;

假设您的端口是0xfeff,您正在做的是:

result |= 0xfeff00;
result |= 0x00feff;

那(第一行)没有做一些有用的事情,并将覆盖ip地址中的最低有效字节。但这不是造成问题的原因 - 您需要使用1.2.3.4:65534之类的不同数字来查看问题。

你应该做的是:

result |= port & 0xFFFF;

& 0xFFFF部分是为了保护您的代码免受负数和数字65535的影响,因为否则会覆盖IP#)

要解码,你正在做:

long port  = ((i >> 8) & 0xFF) | (i & 0xFF);

现在假设long的最低16位包含0xFFFF,那么您的代码就是:

long port = ((0xFFFF >> 8) & 0xFF) | (0xFFF & 0xFF)
          =  0xFF                  | 0xFF
          =  0xFF;

相反,您期望0xFFFF。改为:

long port = (i & 0xFFFF);

答案 1 :(得分:2)

那是因为你把所有东西都移了8位。 8位中可能的最大数字是255(= 11111111)。如果要存储高于255的数字,则必须移位8位以上。 255 = 11111111 = 8位,
65535 = 1111111111111111 = 16位。
这意味着你将不得不将所有内容转移8位:

long result = 0;
result |= Long.parseLong(ip[0]) << 48;
result |= Long.parseLong(ip[1]) << 40;
result |= Long.parseLong(ip[2]) << 32;
result |= Long.parseLong(ip[3]) << 24;

result |= port << 16;

接下来,为什么要获得端口和ip-address,如:

int port = Integer.parseInt(ipAddress.substring(ipAddress.indexOf(":") + 1, ipAddress.length()));
ipAddress = ipAddress.replace(":", "").replace(""+port, "");

当你也可以选择这样做时:

String[] ipadressandport = ipAddress.split(":");
int port = Integer.parseInt(ipaddressandport[1]);
String[] ip = ipaddressandport[0].split("\\.");

看起来更清洁,也更快。