1. 程式人生 > >網路程式設計--位元組序--主機位元組序與網路位元組序介紹及轉換

網路程式設計--位元組序--主機位元組序與網路位元組序介紹及轉換

一、位元組序

位元組序:是指整數在記憶體中儲存的順序。

位元組序有兩種實現方式:

小端位元組序(little endian):低位元組資料存放在記憶體低地址處,高位元組資料存放在記憶體高地址處。

大端位元組序(bigendian):高位元組資料存放在低地址處,低位元組資料存放在高地址處。

如圖所示:


大位元組序更符合我們的閱讀習慣。但是我們的主機使用的是哪種位元組序取決於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));
	}
}

喜歡的朋友點個贊哦~~