我试图将一个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
谢谢!
答案 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("\\.");
看起来更清洁,也更快。