【linux网络编程】网络字节序、地址转换
網絡字節序
故事的起源
“endian”這個詞出自《格列佛游記》。小人國的內戰就源于吃雞蛋時是究竟從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開,由此曾發生過六次叛亂,其中一個皇帝送了命,另一個丟了王位。
我們一般將“endian”翻譯成“字節序”,將?Big-Endian?和 Little-Endian?稱作“大端格式”和“小端格式”。
字節序
字節序是指多字節數據的存儲順序,在設計計算機系統的時候,有兩種處理內存中數據的方法:大端格式、小端格式。
小端格式(Little-Endian):將低位字節數據存儲在低地址。
大端格式(Big-Endian):將高位字節數據存儲在低地址。
舉個簡單的例子,對于整形 0x12345678,它在大端格式和小端格式的系統中,分別如下圖所示的方式存放:
下面例子為確定主機的字節序:
#include <stdio.h>int main(int argc, char *argv) {unsigned int a = 0x11223344;unsigned char *p = (unsigned char *)&a;if (*p == 0x44)printf("Little endian...\n");elseprintf("Big endian....\n");return 0; }
輸出結果為:
[root@localhost 9network]# ./a.out Little endian... [root@localhost 9network]#
網絡上的數據流是字節流,對于一個多字節數值,在進行網絡傳輸的時候,先傳遞哪個字節?也就是說,當接收端收到第一個字節的時候,它是將這個字節作為高位還是低位來處理呢?
?
網絡字節序定義:收到的第一個字節被當作高位看待,這就要求發送端發送的第一個字節應當是高位。而在發送端發送數據時,發送的第一個字節是該數字在內存中起始地址對應的字節。可見多字節數值在發送前,在內存中數值應該以大端法存放。 ?
所以,網絡協議指定了通訊字節序:大端。只有在多字節數據處理時才需要考慮字節序,運行在同一臺計算機上的進程相互通信時,一般不用考慮字節序,異構計算機之間通訊,需要轉換自己的字節序為網絡字節序。
字節序轉換函數介紹
以下接口所需頭文件:#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
返回值:
成功:返回網絡字節序的值
測試示例:?
#include <stdio.h> #include <arpa/inet.h>int main(int argc, char *argv[]) {int a = 0x11223344;short b = 0x1122;printf("htonl(%p): %p\n", a, htonl(a));printf("htons(%p): %p\n", b, htons(b));return 0; }運行結果如下:
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 、 失敗返回其它
測試示例:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h>int main(void) {unsigned long ip = 0;unsigned char *p = NULL;inet_pton(AF_INET, "192.168.10.100", &ip);printf("ip = %lu\n", ip);p = (char*)&ip;printf("%d %d %d %d\n", *p, *(p + 1), *(p + 2), *(p + 3));return 0; }
運行結果如下:
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
測試示例:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h>int main(int argc, char **argv) {unsigned char ip[] = {192, 168, 10, 100};char buf[16] = {0};inet_ntop(AF_INET, ip, buf, 16);printf("buf: %s\n", buf);return 0; }
運行結果如下:
參考網址:http://blog.csdn.net/sunshine1314/article/details/2309655
總結
以上是生活随笔為你收集整理的【linux网络编程】网络字节序、地址转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Linux网络编程】浅谈 C/S 和
- 下一篇: 【物联网】QCA4010开发环境的搭建