htons/ntohs、inet_aton/inet_ntoa、inet_pton/inet_ntop函數詳解

在介紹htons等函數之前,必須先介紹網絡字節序與主機字節序

網絡字節序和主機字節序

網絡字節順序NBO(Network Byte Order): 按從高到低的順序存儲,在網絡上使用統一的網絡字節順序,可以避免兼容性問題。
主機字節順序(HBO,Host Byte Order): 不同的機器HBO不相同,與CPU設計有關,數據的順序是由cpu決定的,而與操作系統無關。

主機字節序就是我們平常說的大端和小端模式:不同的CPU有不同的字節序類型,這些字節序是指整數在內存中保存的順序,這個叫做主機序。引用標準的Big-EndianLittle-Endian的定義如下:
a)Little-Endian就是低位字節排放在內存的低地址端,高位字節排放在內存的高地址端。
b) Big-Endian就是高位字節排放在內存的低地址端,低位字節排放在內存的高地址端。

網絡字節序:4個字節的32bit值以下面的次序傳輸:首先是0~7bit,其次8~15bit,然後16~23bit,最後是24~31bit。這種傳輸次序稱作大端字節序。由於TCP/IP首部中所有的二進制整數在網絡中傳輸時都要求以這種次序,因此它又稱作網絡字節序。

注意:在將一個地址綁定到socket的時候,請先將主機字節序轉換成爲網絡字節序再賦給socket,而不要假定主機字節序跟網絡字節序一樣使用的是Big-Endian。

htonl、htons、ntohl、ntohs

#include <arpa/inet.h>	//函數頭文件

uint32_t htonl(uint32_t hostlong);//32位的主機字節序轉換到網絡字節序
uint16_t htons(uint16_t hostshort);//16位的主機字節序轉換到網絡字節序
uint32_t ntohl(uint32_t netlong);//32位的網絡字節序轉換到主機字節序
uint16_t ntohs(uint16_t netshort);//16位的網絡字節序轉換到主機字節序

這裏通過調用兩個函數htons()htolnl()分別用來將 端口和IP地址轉換成網絡字節序;
這兩個函數名中的 h表示host, n表示network, s表示short(2字節/16位), l表示long(4字節/32位)。
因爲端口號16位的,所以我們用htons()把端口號從主機字節 序轉換成網絡字節序, 而IP地址32位的,所以我們用htonl()函數把IP地址從主機字節序轉換成網絡字節序
hostlongnetlong參數:可當作是4字節(32位)整數;
hostshortnetshort參數:可當作是2字節(16位)整數。

其它函數同理可得,這裏不再贅述。

這裏注意: uint8_t / uint16_t / uint32_t /uint64_t類型解釋如下,如以瞭解,可自行忽略。
按照posix標準,一般整形對應的*_t類型爲:

1字節     uint8_t
2字節     uint16_t
4字節     uint32_t
8字節     uint64_t

這些數據類型是 C99 中定義的,具體定義在:/usr/include/stdint.h ISO C99: 7.18 Integer types <stdint.h>

/* There is some amount of overlap with <sys/types.h> as known by inet code */
#ifndef __int8_t_defined
# define __int8_t_defined
typedef signed char             int8_t; 
typedef short int               int16_t;
typedef int                     int32_t;
# if __WORDSIZE == 64
typedef long int                int64_t;
# else
__extension__
typedef long long int           int64_t;
# endif
#endif

/* Unsigned.  */
typedef unsigned char           uint8_t;
typedef unsigned short int      uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int            uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int       uint64_t;
#else
__extension__
typedef unsigned long long int  uint64_t;
#endif

inet_aton、inet_ntoa(IPv4)

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int inet_aton(const char *cp, struct in_addr *inp);//點分十進制字符串轉換成網絡字節序
char *inet_ntoa(struct in_addr in);	//網絡字節序轉換成點分十進制字符串

作用inet_aton()點分十進制IP地址轉換爲網絡字節序IP地址存儲在in_addr結構體當中;
cp參數:字符串常量(點分十進制IP地址)
inp參數:轉換結果存儲在IPv4結構體中;
函數成功執行則返回該網絡字節序表示的無符號整數

作用inet_ntoa()網絡字節序IP地址轉換爲點分十進制IP地址
in參數:IPv4結構體當中IP地址;
函數成功指向則返回指向點分十進制字符串指針

注意:對inet_aton()的調用傳遞的是指向結構體的指針,而對inet_ntoa()的調用傳遞的是結構體本身

inet_pton、inet_ntop(IPv4與IPv6)

#include <arpa/inet.h>

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

功能inet_pton()函數用於將文本字符串轉換成網絡字節序的二進制地址;
family參數:AF_INET(ipv4)、AF_INET6(ipv6);
strptr參數:指針指向等待轉換的字符串;
addrptr參數:轉換成功的二進制結果;
若成功則返回值爲1,否則如果所指定的family而言輸入字符串不是有效的表達式格式,那麼返回值爲0。

功能inet_ntop()函數用於將網絡字節序的二進制地址轉換成文本字符串;
family參數:AF_INET(ipv4)、AF_INET6(ipv6);
strptr參數:指針指向等待轉換的字符串,不可以是一個空指針;
addrptr參數:轉換成功的二進制結果;
調用者必須爲目標存儲單元分配內存並指定其大小,調用成功時,這個指針就是該函數的返回值。
len參數:目標 存儲單元的大小,以免該函數溢出其調用者的緩衝區。如果len太小,不足以容納表達式結果,那麼返回一個空指針,並置爲errno爲ENOSPC。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章