天天看點

Linux 網絡程式設計——網絡位元組序、位址轉換

一、位元組序的概念

位元組序是指多位元組資料的存儲順序,在設計計算機系統的時候,有兩種處理記憶體中資料的方法:大端格式、小端格式。

小端格式(Little-Endian):将低位位元組資料存儲在低位址。

大端格式(Big-Endian):将高位位元組資料存儲在低位址。

Linux 網絡程式設計——網絡位元組序、位址轉換
舉個簡單的例子,對于整形 0x12345678,它在大端格式和小端格式的系統中,分别如下圖所示的方式存放:
Linux 網絡程式設計——網絡位元組序、位址轉換
下面例子為确定主機的位元組序:

[objc] view plaincopy

Linux 網絡程式設計——網絡位元組序、位址轉換
Linux 網絡程式設計——網絡位元組序、位址轉換
  1. #include <stdio.h>  
  2. int main(int argc, charchar *argv[])  
  3. {  
  4.     unsigned int a = 0x12345678;  
  5.     unsigned char *p = (unsigned charchar *)&a; //隻取一個位元組  
  6.     if(0x12 == *p){  
  7.         printf("Big-Endian\n");  
  8.     }else if(0x78 == *p){  
  9.         printf("Little-Endian\n");  
  10.     }  
  11.     return 0;  
  12. }  
網絡上的資料流是位元組流,對于一個多位元組數值,在進行網絡傳輸的時候,先傳遞哪個位元組?也就是說,當接收端收到第一個位元組的時候,它是将這個位元組作為高位還是低位來處理呢?
網絡位元組序定義:收到的第一個位元組被當作高位看待,這就要求發送端發送的第一個位元組應當是高位。而在發送端發送資料時,發送的第一個位元組是該數字在記憶體中起始位址對應的位元組。可見多位元組數值在發送前,在記憶體中數值應該以大端法存放。  
是以,網絡協定指定了通訊位元組序:大端。隻有在多位元組資料處理時才需要考慮位元組序,運作在同一台計算機上的程序互相通信時,一般不用考慮位元組序,異構計算機之間通訊,需要轉換自己的位元組序為網絡位元組

二、位元組序轉換函數介紹

以下接口所需頭檔案:#include <arpa/inet.h>

uint32_t htonl(uint32_t hostint32);

功能:

将 32 位主機位元組序資料轉換成網絡位元組序資料
參數:
hostint32:需要轉換的 32 位主機位元組序資料,uint32_t 為 32 為無符号整型
傳回值:
成功:傳回網絡位元組序的值

uint16_t htons(uint16_t hostint16);

功能:

将 16 位主機位元組序資料轉換成網絡位元組序資料
參數:
hostint16:需要轉換的 16 位主機位元組序資料,uint16_t,unsigned short int
傳回值:
成功:傳回網絡位元組序的值
測試示例:

[objc] view plaincopy

Linux 網絡程式設計——網絡位元組序、位址轉換
Linux 網絡程式設計——網絡位元組序、位址轉換
  1. #include <stdio.h>  
  2. #include <arpa/inet.h>  
  3. int main(int argc, charchar *argv[])  
  4. {  
  5.     int a = 0x01020304;  
  6.     short int b = 0x0102;  
  7.     printf("htonl(0x%08x) = 0x%08x\n", a, htonl(a));  
  8.     printf("htons(0x%04x) = 0x%04x\n", b, htons(b));  
  9.     return 0;  
  10. }  
運作結果如下:
Linux 網絡程式設計——網絡位元組序、位址轉換

uint32_t ntohl(uint32_t netint32);

功能:

将 32 位網絡位元組序資料轉換成主機位元組序資料
參數:
netint32:待轉換的 32 位網絡位元組序資料,uint32_t,unsigned int
傳回值:
成功:傳回主機位元組序的值

uint16_t ntohs(uint16_t netint16);

功能:

将 16 位網絡位元組序資料轉換成主機位元組序資料
參數:
netint16:待轉換的 16 位網絡位元組序資料,uint16_t,unsigned short int

傳回值:

成功:傳回主機位元組序的

三、位址轉換函數

以下接口所需頭檔案:#include <arpa/inet.h>

int inet_pton(int family, const char *strptr, void *addrptr);

功能:

将點分十進制數串轉換成 32 位無符号整數
參數:
family:協定族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET
strptr:點分十進制數串
addrptr:32 位無符号整數的位址
傳回值:
成功傳回 1 、 失敗傳回其它
測試示例:

[objc] view plaincopy

Linux 網絡程式設計——網絡位元組序、位址轉換
Linux 網絡程式設計——網絡位元組序、位址轉換
  1. #include <stdio.h>  
  2. #include <arpa/inet.h>  
  3. int main()  
  4. {  
  5.     char ip_str[]="172.20.223.75";  
  6.     unsigned int ip_uint = 0;  
  7.     unsigned charchar *ip_p = NULL;  
  8.     inet_pton(AF_INET,ip_str,&ip_uint);  
  9.     printf("in_uint = %d\n",ip_uint);  
  10.     ip_p = (charchar *)&ip_uint;  
  11.     printf("in_uint = %d,%d,%d,%d\n",*ip_p,*(ip_p+1),*(ip_p+2),*(ip_p+3));  
  12.     return 0;  
  13. }  
運作結果如下:
Linux 網絡程式設計——網絡位元組序、位址轉換
const char *inet_ntop( int family, 
const void *addrptr,   
char *strptr, 
size_t len );
功能:
将 32 位無符号整數轉換成點分十進制數串
參數:
family:協定族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET
addrptr:32 位無符号整數
strptr:點分十進制數串
len:strptr 緩存區長度
len 的宏定義
#define INET_ADDRSTRLEN   16  // for ipv4
#define INET6_ADDRSTRLEN  46  // for ipv6
傳回值:
成功:則傳回字元串的首位址
失敗:傳回 NULL
測試示例:

[objc] view plaincopy

Linux 網絡程式設計——網絡位元組序、位址轉換
Linux 網絡程式設計——網絡位元組序、位址轉換
  1. #include <stdio.h>  
  2. #include <arpa/inet.h>  
  3. int main()  
  4. {  
  5.     unsigned char ip[] = {172,20,223,75};  
  6.     char ip_str[16] = "NULL";  
  7.     inet_ntop(AF_INET,(unsigned intint *)ip,ip_str,16);  
  8.     printf("ip_str = %s\n",ip_str);  
  9.     return 0;  
  10. }  
運作結果如下:
Linux 網絡程式設計——網絡位元組序、位址轉換

測試示例代碼下載下傳請點此處。

轉自:http://blog.csdn.net/tennysonsky/article/details/45045549