1. 程式人生 > >主機位元組序與網路位元組序的轉換函式:htonl、ntohl、htons、ntohs

主機位元組序與網路位元組序的轉換函式:htonl、ntohl、htons、ntohs

Part 1: htons函式具體解釋
     在Linux和Windows網路程式設計時需要用到htons和htonl函式,用來將主機位元組順序轉換為網路位元組順序。

     在Intel機器下,執行以下程式

int main()
...{
   printf("%d /n",htons(16));
      return 0;
}
得到的結果是4096,初一看感覺很怪。

    解釋如下,數字16的16進製表示為0x0010,數字4096的16進製表示為0x1000。 由於Intel機器是小尾端,儲存數字16時實際順序為1000,儲存4096時實際順序為0010。因此在傳送網路包時為了報文中資料為0010,需要經過htons進行位元組轉換。如果用IBM等大尾端機器,則沒有這種位元組順序轉換,但為了程式的可移植性,也最好用這個函式。

   另外用注意,數字所佔位數小於或等於一個位元組(8 bits)時,不要用htons轉換。這是因為對於主機來說,大小尾端的最小單位為位元組(byte)。

Part 2: 大小端模式


不同的CPU有不同的位元組序型別 這些位元組序是指整數在記憶體中儲存的順序 這個叫做主機序 
最常見的有兩種
1. Little endian:將低序位元組儲存在起始地址
2. Big endian:將高序位元組儲存在起始地址

LE little-endian 
最符合人的思維的位元組序 
地址低位儲存值的低位 
地址高位儲存值的高位 
怎麼講是最符合人的思維的位元組序,是因為從人的第一觀感來說 
低位值小,就應該放在記憶體地址小的地方,也即記憶體地址低位 
反之,高位值就應該放在記憶體地址大的地方,也即記憶體地址高位

BE big-endian 
最直觀的位元組序 
地址低位儲存值的高位 
地址高位儲存值的低位 
為什麼說直觀,不要考慮對應關係 
只需要把記憶體地址從左到右按照由低到高的順序寫出 
把值按照通常的高位到低位的順序寫出 
兩者對照,一個位元組一個位元組的填充進去

例子:在記憶體中雙字0x01020304(DWORD)的儲存方式

記憶體地址 
4000 4001 4002 4003 
LE 04 03 02 01 
BE 01 02 03 04

例子:如果我們將0x1234abcd寫入到以0x0000開始的記憶體中,則結果為
      big-endian  little-endian
0x0000  0x12      0xcd
0x0001  0x23      0xab
0x0002  0xab      0x34
0x0003  0xcd      0x12
x86系列CPU都是little-endian的位元組序.

網路位元組順序是TCP/IP中規定好的一種資料表示格式,它與具體的CPU型別、作業系統等無關,從而可以保證資料在不同主機之間傳輸時能夠被正確解釋。網路位元組順序採用big endian排序方式。

為了進行轉換 bsd socket提供了轉換的函式 有下面四個
htons 把unsigned short型別從主機序轉換到網路序
htonl 把unsigned long型別從主機序轉換到網路序
ntohs 把unsigned short型別從網路序轉換到主機序
ntohl 把unsigned long型別從網路序轉換到主機序

在使用little endian的系統中 這些函式會把位元組序進行轉換 
在使用big endian型別的系統中 這些函式會定義成空巨集

同樣 在網路程式開發時 或是跨平臺開發時 也應該注意保證只用一種位元組序 不然兩方的解釋不一樣就會產生bug.

注:
1、網路與主機位元組轉換函式:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)
2、不同的CPU上執行不同的作業系統,位元組序也是不同的,參見下表。
處理器    作業系統    位元組排序
Alpha    全部    Little endian
HP-PA    NT    Little endian
HP-PA    UNIX    Big endian
Intelx86    全部    Little endian <-----x86系統是小端位元組序系統
Motorola680x()    全部    Big endian
MIPS    NT    Little endian
MIPS    UNIX    Big endian
PowerPC    NT    Little endian
PowerPC    非NT    Big endian  <-----PPC系統是大端位元組序系統
RS/6000    UNIX    Big endian
SPARC    UNIX    Big endian
IXP1200 ARM核心    全部    Little endian

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.NET/zouxinfox/archive/2007/10/07/1814088.aspx

Part 3: 模擬htonl、ntohl、htons、ntohs函式實現


--------------------------------------------------------------------------------
今天在如鵬網裡討論htonl、ntohl在不同機器的區別,特意模擬了htonl、ntohl、htons、ntohs函式實現。
實現如下:


typedef unsigned short int uint16;

typedef unsigned long int uint32;

// 短整型大小端互換

#define BigLittleSwap16(A)  ((((uint16)(A) & 0xff00) >> 8) | /

                                                 (((uint16)(A) & 0x00ff) << 8))

// 長整型大小端互換

#define BigLittleSwap32(A)  ((((uint32)(A) & 0xff000000) >> 24) | /

                                                 (((uint32)(A) & 0x00ff0000) >> 8) | /

                                                 (((uint32)(A) & 0x0000ff00) << 8) | /

                                                 (((uint32)(A) & 0x000000ff) << 24))

// 本機大端返回1,小端返回0

int checkCPUendian()

{

       union{

              unsigned long int i;

              unsigned char s[4];

       }c;

       c.i = 0x12345678;

       return (0x12 == c.s[0]);

}

// 模擬htonl函式,本機位元組序轉網路位元組序

unsigned long int HtoNl(unsigned long int h)

{

       // 若本機為大端,與網路位元組序同,直接返回

       // 若本機為小端,轉換成大端再返回

       return checkCPUendian() ? h : BigLittleSwap32(h);

}

// 模擬ntohl函式,網路位元組序轉本機位元組序

unsigned long int NtoHl(unsigned long int n)

{

       // 若本機為大端,與網路位元組序同,直接返回

       // 若本機為小端,網路資料轉換成小端再返回

       return checkCPUendian() ? n : BigLittleSwap32(n);

}

// 模擬htons函式,本機位元組序轉網路位元組序

unsigned short int HtoNs(unsigned short int h)

{

       // 若本機為大端,與網路位元組序同,直接返回

       // 若本機為小端,轉換成大端再返回

       return checkCPUendian() ? h : BigLittleSwap16(h);

}

// 模擬ntohs函式,網路位元組序轉本機位元組序

unsigned short int NtoHs(unsigned short int n)

{

       // 若本機為大端,與網路位元組序同,直接返回

       // 若本機為小端,網路資料轉換成小端再返回

       return checkCPUendian() ? n : BigLittleSwap16(n);

}

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.Net/fjiale/archive/2010/06/25/5693509.aspx

相關推薦

主機位元組網路位元組轉換

小端位元組序:即一個整數的高位位元組存放在記憶體中的高位地址處,低位位元組存放在記憶體中的低位地址處 大端位元組序:與小端位元組序剛好相反 現代的pc多采用小端位元組序,而java虛擬機器採用大端位元組序,網路採用的也是大端位元組序 所以在網路傳輸中通常我們需要進行位元組

主機位元組網路位元組轉換函式htonlntohlhtonsntohs

Part 1: htons函式具體解釋      在Linux和Windows網路程式設計時需要用到htons和htonl函式,用來將主機位元組順序轉換為網路位元組順序。      在Intel機器下,執行以下程式 int main() ...{    printf(

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

一、位元組序位元組序:是指整數在記憶體中儲存的順序。位元組序有兩種實現方式:小端位元組序(little endian):低位元組資料存放在記憶體低地址處,高位元組資料存放在記憶體高地址處。大端位元組序(bigendian):高位元組資料存放在低地址處,低位元組資料存放在高地址

Python Network Programming(4)---主機位元組網路位元組之間的相互轉換

編寫低層網路應用時,或許需要處理通過電纜在兩臺裝置之間傳送的低層資料,這種操作中,需要把主機作業系統發出的資料轉換成網路格式,或者做逆向轉換,因為這兩種資料的表示方式不一樣。 位元組序相關見u

主機位元組網路位元組轉換ntohl()htonl()

#!/usr/bin/env python #coding=utf-8 import socket def convert_integer(): data=1234 #32-bit prin

主機位元組 網路位元組

一、位元組順序 是指佔用記憶體多於一個位元組型別的資料在記憶體中的存放順序。 計算機電路先處理低位位元組,效率比較高,因為計算都是從低位開始的。所以,計算機的內部處理都是小端位元組序。 但是,網路傳輸、檔案儲存、人類讀寫習慣使用大端位元組序。   java中一個int型資料

主機位元組網路位元組

1 主機位元組序 主機位元組序(host-byte)指的是處理器儲存資料的位元組順序。對於Inter x86處理器來說,將資料的不重要的部分儲存在低地址,重要的部分儲存在高地址,即低地址中儲存的是資料的低位元組位,高地址儲存的是資料的高位元組位。 int ip_Addre

網路通訊之 位元組轉換原理網路位元組大端和小端模式

     原因如下:網路協議規定接收到得第一個位元組是高位元組,存放到低地址,所以傳送時會首先去低地址取資料的高位元組。小端模式的多位元組資料在存放時,低地址存放的是低位元組,而被髮送方網路協議函式傳送時會首先去低地址取資料(想要取高位元組,真正取得是低位元組),接收方網路協議函式接收時會將接收到的第一個位元

java 位元組陣列int型別互相轉換

public class test { public static void main(String[] args) throws ParseException { int i=-6123; System.out.println(bytes2int(int2

將圖片(二進位制檔案)儲存於資料庫,論檔案位元組二進位制字串相互轉換

開發中遇到儲存圖片檔案於資料庫這樣的需求。我們知道檔案本身就是一份二進位制資料,不同型別的檔案只是編碼形式不同,對應的解讀形式不同,無論txt檔案、jpg檔案亦或是mp4檔案,本質上都是0和1組成的。而在C++中我們可以通過位元組流來讀寫檔案,也就是說我們可以把檔案讀入cha

黑馬程式設計師位元組字元流的轉換/ObjectOutputStream;ObjectInputStream

ObjectInputStream和 ObjectOutputStream這兩個包裝類,              用於從底層輸入流中讀取物件型別的資料和將物件型別的資料寫入到底層輸出流。ObjectInputStream與ObjectOutputSream類所讀寫的物件必須

矩陣的行主列主

1.矩陣在記憶體中的儲存     不管是D3D還是OpenGL,使用的矩陣都是線性代數標準的矩陣,只是在儲存方式上有所不同。分別為:行主序(Direct3D),列主序(OpenGL)     儲存順序說明了線性代數中的矩陣如何線上性的記憶體陣列中儲存。     例如:

Java位元組Dalvik位元組

JVM語言無關性 JVM只與位元組碼關聯,而不與Java語言直接關聯。事實上,JRuby,Groovy等語言也可以由相應的編譯器編譯為位元組碼,然後由JVM解釋執行。甚至可以自己寫一個class

java 位元組高效位元組流的區別

import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream;

漢字區位碼(1) - 轉換函式

先上轉換函式:   unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,   Dialogs, StdCtrls;

PHP圖片base64字串相互轉換函式

/** * base64字串轉換成圖片 * @param string $base64_string base64字串 * @param unknown $path 圖片儲存路徑 * @param string $prefix 圖片字首 * @return boolean */ function

JNI中jstring const char* 相互轉換函式

在平時的工作,經常用到jni和const型別轉換。 //將const char型別轉換成jstring型別 jstring CStr2Jstring( JNIEnv* env, const char* pat ) { //定義java String類 strClass j

關於python的字串大小轉換函式capitalize() title() upper() swapcase()

原以為寫了,找的我好苦!結果竟然沒寫! 補上: capitalize():讓字串首字母變成大寫! title():所有單詞開頭字母變成大寫! upper():整個字串的所有字母變成大寫! swapcase():所有字母進行大小寫轉換! 程式碼:

轉換函式TO_CHAR()用法之一 將一個數值轉化成字串

 格式:TO_CHAR(number,format) 即 TO_CHAR((數值,格式) 用法: 1、不指定格式的 TO_CHAR函式將數值轉換成簡單字串形式。         例:  TO_CHAR(123)       結果       123       

IP地址格式轉換htonlntohl;inet_addrinet_ntoa)

1、htonl ()和ntohl( ) u_long PASCAL FAR ntohl (u_long netlong); u_short PASCAL FAR ntohs (u_short netshort); ntohl( )-----網路順序轉換成主機順序 u_lo