網路程式設計--位元組序--主機位元組序與網路位元組序介紹及轉換
一、位元組序
位元組序:是指整數在記憶體中儲存的順序。
位元組序有兩種實現方式:
小端位元組序(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型別從網路序轉換到主機序
二、主機位元組序與網路位元組序
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)); } }