网络编程--字节序--主机字节序与网络字节序介绍及转换

一、字节序

字节序:是指整数在内存中保存的顺序。

字节序有两种实现方式:

小端字节序(little endian):低字节数据存放在内存低地址处,高字节数据存放在内存高地址处。

大端字节序(bigendian):高字节数据存放在低地址处,低字节数据存放在高地址处。

如图所示:

网络编程--字节序--主机字节序与网络字节序介绍及转换_第1张图片

大字节序更符合我们的阅读习惯。但是我们的主机使用的是哪种字节序取决于CPU,不同的CPU型号有不同的选择。

那么如何确定我们主机使用的哪种字节序。这里提供了两种方式:

方式1:

public class JVMEndianTest2 {
	public static void main(String[] args) {
		int x = 0x01020304;
		ByteBuffer bb = ByteBuffer.wrap(new byte[4]);
		bb.asIntBuffer().put(x);
		String ss_before = Arrays.toString(bb.array());
		System.out.println("默认字节序 " + bb.order().toString() + "," + " 内存数据 " + ss_before);
		bb.order(ByteOrder.LITTLE_ENDIAN);
		bb.asIntBuffer().put(x);
		String ss_after = Arrays.toString(bb.array());
		System.out.println("修改字节序 " + bb.order().toString() + "," + " 内存数据 " + ss_after);
	}
}

方式2:

public class JVMEndianTest {
	public static void main(String[] args) throws IOException {
		int a = 0x12345678;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(baos);
		dos.writeInt(a);
		byte[] b = baos.toByteArray();
		for (int i = 0; i < 4; i++) {
			System.out.println(Integer.toHexString(b[i]));
		}
	}
}

四种需要了解的网络与主机字节转换函数(当你自己写转换方法时可以使用这个进行起名):

htons() 把unsigned short类型从主机序转换到网络序

htonl() 把unsigned long类型从主机序转换到网络序

ntohs() 把unsigned short类型从网络序转换到主机序

ntohl() 把unsigned long类型从网络序转换到主机序

二、主机字节序与网络字节序

1.主机字节序:主机内部内存中数据的处理方式。

2.网络字节序:网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian(大端)排序方式。

3.主机字节序与网络字节序之间的转换:

第一步   127     .         0         .         0         .        1                 把IP地址每一部分转换为8位的二进制数。

第二步 01111111     00000000     00000000     00000001      =   2130706433   (主机字节序)

然后把上面的四部分二进制数从右往左按部分重新排列,那就变为:

第三步 00000001     00000000     00000000    01111111        =   16777343        (网络字节序)

4.实现方式(Java):

可以实现字符串ip与主机序,网络字节序之间的转换。

public class IPUtils {

	// 把字符串ip转成网络字节序
	public static Long iphtonl(String ip) {
		if (ip == null || ip.length() == 0)
			return null;
		else if (ip.equals("0"))
			return 0L;
		long ip10 = 0;
		String[] ss = ip.trim().split("\\.");
		if (ss.length != 4)
			return 0L;
		for (int i = 0; i < 4; i++) {
			ip10 |= Long.parseLong(ss[i]) << ((i) * 8);
		}
		return ip10;
	}

	// 把字符串ip转成主机序
	public static Long iphtonl2(String ip) {
		if (ip == null || ip.length() == 0)
			return null;
		else if (ip.equals("0"))
			return 0L;
		long ip10 = 0;
		String[] ss = ip.trim().split("\\.");
		if (ss.length != 4)
			return 0L;
		ip10 |= Long.parseLong(ss[0]) << 24;
		ip10 |= Long.parseLong(ss[1]) << 16;
		ip10 |= Long.parseLong(ss[2]) << 8;
		ip10 |= Long.parseLong(ss[3]) << 0;
		return ip10;
	}

	// 把网络字节序的IP转成字符串IP
	public static String htonlip(Long ip) {
		if (ip == null)
			return "";
		return ((ip >> 0) & 0x0ff) + "." + ((ip >> 8) & 0x0ff) + "." + ((ip >> 16) & 0x0ff) + "."
				+ ((ip >> 24) & 0x0ff);
	}

	// 把主机字节序的ip专横字符串ip
	public static String htonlip2(Long ip) {
		if (ip == null)
			return "";
		return ((ip >> 24) & 0x0ff) + "." + ((ip >> 16) & 0x0ff) + "." + ((ip >> 8) & 0x0ff) + "."
				+ ((ip >> 0) & 0x0ff);
	}

	public static void main(String[] args) {
		System.out.println("字符串IP->主机字节序:" + iphtonl2("1.0.0.0"));
		System.out.println("字符串IP->网络字节序:" + iphtonl("1.0.0.0"));
		System.out.println("网络字节序->字符串IP:" + htonlip(1L));
		System.out.println("主机字节序->字符串IP:" + htonlip(16777216L));
	}
}

喜欢的朋友点个赞哦~~


你可能感兴趣的:(Java)