日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络字节序与主机字节序的相互转换

發布時間:2024/1/8 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络字节序与主机字节序的相互转换 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.網絡字節序與主機字節序

在Linux網絡編程中,經常碰到網絡字節序與主機字節序的相互轉換。說到網絡字節序與主機字節序需要清晰了解以下幾個概念。

字節序,顧名思義,指字節在內存中存儲的順序。比如一個int32_t類型的數值占用4個字節,這4個字節在內存中的排列順序就是字節序。字節序有兩種:
(1)小端字節序(Little endinan),數值低位存儲在內存的低地址,高位存儲在內存的高地址;
(2)大端字節序(Big endian),數值高位存儲在內存的低地址,低位存儲在內存的高地址。

下面以32位位寬數值0x12345678為例,小端字節序與大端字節序具體的存儲區別如下所示:

主機字節序,即CPU存儲數據時采用的字節順序。不同的CPU設計時采用的字節序是不同的,談到字節序的問題,必然牽涉到兩大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86與x86_64(該指令集由AMD率先設計推出)系列CPU。PowerPC系列采用big endian方式存儲數據,而x86與x86_64系列則采用little endian方式存儲數據。平常大多數PC與服務器如果使用的是Intel與AMD CPU,一般都是little endian。

如何具體判斷本機的主機字節序呢?參考如下代碼:

//@ret:返回0小端字節序,返回1大端字節序 int dGetHostByteOrder() {uint32_t a = 0x12345678; uint8_t *p = (uint8_t *)(&a); if(*p==0x78){return 0}else{return 1;} }

網絡字節序,是TCP/IP中規定好的一種數據表示格式,它與具體的CPU類型、操作系統等無關,從而可以保證數據在不同主機之間傳輸時能夠被正確解釋。網絡字節順序采用big endian排序方式。

2.網絡字節序與主機字節序的相互轉換

2.1常用系統調用

Linux socket網絡編程中,經常會使用下面四個C標準庫函數進行字節序間的轉換。

#include <arpa/inet.h>uint32_t htonl(uint32_t hostlong); //把uint32_t類型從主機序轉換到網絡序 uint16_t htons(uint16_t hostshort); //把uint16_t類型從主機序轉換到網絡序 uint32_t ntohl(uint32_t netlong); //把uint32_t類型從網絡序轉換到主機序 uint16_t ntohs(uint16_t netshort); //把uint16_t類型從網絡序轉換到主機序

2.2 64位數值的轉換

現在如果需要對64位類型數據進行主機字節序與網絡字節序的轉換,沒有現成系統API可用,可以通過下面兩種方法進行轉換:

###2.2.1使用移位

//主機序轉網絡序 unsigned long long htonll(unsigned long long val) {if(__BYTE_ORDER == __LITTLE_ENDIAN) {return (((unsigned long long )htonl((int)((val << 32) >> 32))) << 32) | (unsigned int)htonl((int)(val >> 32)); } else if (__BYTE_ORDER == __BIG_ENDIAN) { return val; } } //網絡序轉主機序 unsigned long long ntohll(unsigned long long val) { if (__BYTE_ORDER == __LITTLE_ENDIAN){return (((unsigned long long )ntohl((int)((val << 32) >> 32))) << 32) | (unsigned int)ntohl((int)(val >> 32)); } else if (__BYTE_ORDER == __BIG_ENDIAN) { return val; }}

2.2.2使用聯合體union

根據聯合體的特性:聯合中所有成員引用的是內存中相同的位置,其長度為最長成員的長度。

typedef struct { unsigned int u32_h; unsigned int u32_l; }Int64_t; typedef union { unsigned long long u64; Int64_t st64; }Convert64_t;//主機序轉網絡序 unsigned long long htonll(unsigned long long val) { if (__BYTE_ORDER == __LITTLE_ENDIAN){Convert64_t box_in, box_out; box_in.u64 = val; box_out.st64.u32_h = htonl(box_in.st64.u32_l); box_out.st64.u32_l = htonl(box_in.st64.u32_h); return box_out.u64;}else if (__BYTE_ORDER == __BIG_ENDIAN) { return val;} }//網絡序轉主機序 unsigned long long ntohll(unsigned long long val) {if (__BYTE_ORDER == __LITTLE_ENDIAN){Convert64_t box_in, box_out; box_in.u64 = val; box_out.st64.u32_h = ntohl(box_in.st64.u32_l); box_out.st64.u32_l = ntohl(box_in.st64.u32_h); return box_out.u64;}else if(__BYTE_ORDER == __BIG_ENDIAN){return val;} }

2.2.3使用編譯器內置函數

#ifdef WIN32 #define ntohll(x) _byteswap_uint64 (x) #define htonll(x) _byteswap_uint64 (x) #else #if __BYTE_ORDER == __BIG_ENDIAN #define ntohll(x) (x) #define htonll(x) (x) #else #if __BYTE_ORDER == __LITTLE_ENDIAN #define ntohll(x) __bswap_64 (x) #define htonll(x) __bswap_64 (x) #endif #endif #endif

參考資料

[1]網絡字節序與主機字節序 高低位
[2]htonl(3) - Linux man page
[3]如何在C ++中的big-endian和little-endian值之間進行轉換?

總結

以上是生活随笔為你收集整理的网络字节序与主机字节序的相互转换的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。