【linux网络编程】网络字节序、地址转换
網(wǎng)絡(luò)字節(jié)序
故事的起源
“endian”這個(gè)詞出自《格列佛游記》。小人國(guó)的內(nèi)戰(zhàn)就源于吃雞蛋時(shí)是究竟從大頭(Big-Endian)敲開還是從小頭(Little-Endian)敲開,由此曾發(fā)生過(guò)六次叛亂,其中一個(gè)皇帝送了命,另一個(gè)丟了王位。
我們一般將“endian”翻譯成“字節(jié)序”,將?Big-Endian?和 Little-Endian?稱作“大端格式”和“小端格式”。
字節(jié)序
字節(jié)序是指多字節(jié)數(shù)據(jù)的存儲(chǔ)順序,在設(shè)計(jì)計(jì)算機(jī)系統(tǒng)的時(shí)候,有兩種處理內(nèi)存中數(shù)據(jù)的方法:大端格式、小端格式。
小端格式(Little-Endian):將低位字節(jié)數(shù)據(jù)存儲(chǔ)在低地址。
大端格式(Big-Endian):將高位字節(jié)數(shù)據(jù)存儲(chǔ)在低地址。
舉個(gè)簡(jiǎn)單的例子,對(duì)于整形 0x12345678,它在大端格式和小端格式的系統(tǒng)中,分別如下圖所示的方式存放:
下面例子為確定主機(jī)的字節(jié)序:
#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; }
輸出結(jié)果為:
[root@localhost 9network]# ./a.out Little endian... [root@localhost 9network]#
網(wǎng)絡(luò)上的數(shù)據(jù)流是字節(jié)流,對(duì)于一個(gè)多字節(jié)數(shù)值,在進(jìn)行網(wǎng)絡(luò)傳輸?shù)臅r(shí)候,先傳遞哪個(gè)字節(jié)?也就是說(shuō),當(dāng)接收端收到第一個(gè)字節(jié)的時(shí)候,它是將這個(gè)字節(jié)作為高位還是低位來(lái)處理呢?
?
網(wǎng)絡(luò)字節(jié)序定義:收到的第一個(gè)字節(jié)被當(dāng)作高位看待,這就要求發(fā)送端發(fā)送的第一個(gè)字節(jié)應(yīng)當(dāng)是高位。而在發(fā)送端發(fā)送數(shù)據(jù)時(shí),發(fā)送的第一個(gè)字節(jié)是該數(shù)字在內(nèi)存中起始地址對(duì)應(yīng)的字節(jié)。可見多字節(jié)數(shù)值在發(fā)送前,在內(nèi)存中數(shù)值應(yīng)該以大端法存放。 ?
所以,網(wǎng)絡(luò)協(xié)議指定了通訊字節(jié)序:大端。只有在多字節(jié)數(shù)據(jù)處理時(shí)才需要考慮字節(jié)序,運(yùn)行在同一臺(tái)計(jì)算機(jī)上的進(jìn)程相互通信時(shí),一般不用考慮字節(jié)序,異構(gòu)計(jì)算機(jī)之間通訊,需要轉(zhuǎn)換自己的字節(jié)序?yàn)榫W(wǎng)絡(luò)字節(jié)序。
字節(jié)序轉(zhuǎn)換函數(shù)介紹
以下接口所需頭文件:#include <arpa/inet.h>
uint32_t htonl(uint32_t hostint32);
功能:
將 32 位主機(jī)字節(jié)序數(shù)據(jù)轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序數(shù)據(jù)
參數(shù):
hostint32:需要轉(zhuǎn)換的 32 位主機(jī)字節(jié)序數(shù)據(jù),uint32_t 為 32 為無(wú)符號(hào)整型
返回值:
成功:返回網(wǎng)絡(luò)字節(jié)序的值
uint16_t htons(uint16_t hostint16);
功能:
將 16 位主機(jī)字節(jié)序數(shù)據(jù)轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序數(shù)據(jù)
參數(shù):
hostint16:需要轉(zhuǎn)換的 16 位主機(jī)字節(jié)序數(shù)據(jù),uint16_t,unsigned short int
返回值:
成功:返回網(wǎng)絡(luò)字節(jié)序的值
測(cè)試示例:?
#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; }運(yùn)行結(jié)果如下:
uint32_t ntohl(uint32_t netint32);
功能:
將 32 位網(wǎng)絡(luò)字節(jié)序數(shù)據(jù)轉(zhuǎn)換成主機(jī)字節(jié)序數(shù)據(jù)
參數(shù):
netint32:待轉(zhuǎn)換的 32 位網(wǎng)絡(luò)字節(jié)序數(shù)據(jù),uint32_t,unsigned int
返回值:
成功:返回主機(jī)字節(jié)序的值
uint16_t ntohs(uint16_t netint16);
功能:
將 16 位網(wǎng)絡(luò)字節(jié)序數(shù)據(jù)轉(zhuǎn)換成主機(jī)字節(jié)序數(shù)據(jù)
參數(shù):
netint16:待轉(zhuǎn)換的 16 位網(wǎng)絡(luò)字節(jié)序數(shù)據(jù),uint16_t,unsigned short int
返回值:
成功:返回主機(jī)字節(jié)序的值
地址轉(zhuǎn)換函數(shù)
以下接口所需頭文件:#include <arpa/inet.h> int inet_pton(int family,?const char *strptr, void *addrptr);
功能:
將點(diǎn)分十進(jìn)制數(shù)串轉(zhuǎn)換成 32 位無(wú)符號(hào)整數(shù)
參數(shù):
family:協(xié)議族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET
strptr:點(diǎn)分十進(jìn)制數(shù)串
addrptr:32 位無(wú)符號(hào)整數(shù)的地址
返回值:
成功返回 1 、 失敗返回其它
測(cè)試示例:
#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; }
運(yùn)行結(jié)果如下:
const char *inet_ntop( int family,?const void *addrptr,???char *strptr,?size_t len );
功能:
將 32 位無(wú)符號(hào)整數(shù)轉(zhuǎn)換成點(diǎn)分十進(jìn)制數(shù)串
參數(shù):
family:協(xié)議族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET
addrptr:32 位無(wú)符號(hào)整數(shù)
strptr:點(diǎn)分十進(jìn)制數(shù)串
len:strptr 緩存區(qū)長(zhǎng)度
len 的宏定義 #define INET_ADDRSTRLEN ? 16 ?// for ipv4#define INET6_ADDRSTRLEN ?46 ?// for ipv6
返回值:
成功:則返回字符串的首地址
失敗:返回 NULL
測(cè)試示例:
#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; }
運(yùn)行結(jié)果如下:
參考網(wǎng)址:http://blog.csdn.net/sunshine1314/article/details/2309655
總結(jié)
以上是生活随笔為你收集整理的【linux网络编程】网络字节序、地址转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【Linux网络编程】浅谈 C/S 和
- 下一篇: 【Linux驱动】linux内核模块简介