純粹copy,記錄一下,講的很細
這兩個函數是随IPv6出現的新函數,對于IPv4位址和IPv6位址都适用。函數名中的p和n非别代表表達(presentation)和數值(numeric)。位址的表達格式通常是ASCII字元串,數值格式則是存放到套接字位址結構中的二進制值。函數如下:
- #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);
- 傳回:若成功則為指向結果的指針, 若出錯則為 NULL
這兩個函數的family參數既可以是AF_INET,也可以是AF_INET6。如果以不被支援的位址族作為family的參數,這兩個函數就都傳回一個錯誤,并将errno置為EAFNOSUPPORT。
第一個函數嘗試轉換由strptr指針所指的字元串,并通過addrptr指針存放二進制結果。若成功則傳回1,否則如果對所指定的family而言輸入的字元串不是有效的表達式,那麼值為0。
inet_ntop進行相反的轉換,從數值格式(addrptr)轉換到表達格式(strptr)。len參數是目标存儲單元的大小,以免該函數溢出其調用者的緩沖區。為有助于指定這個大小,在<netinet/in.h>頭檔案中有如下定義:
- #define INET_ADDRSTRLEN 16
- #define INET6_ADDRSTRLEN 46
如果len太小,不足以容納表達式結果(包括結尾的空字元),那麼傳回一個空指針,并置errno為ENOSPC。
inet_ntop函數的strptr參數不可以是一個空指針。調用者必須為目标存儲單元配置設定記憶體并指定其大小。調用成功時,這個指針就是該函數的傳回值。
即使系統還不支援IPv6,也可以采取下列措施開始使用這些新函數,即用代碼
- inet_pton(AF_INET, cp, &foo.sin_addr);
- 代替代碼
- foo.sin_addr.s_addr = inet_addr(cp);
- 再用代碼
- char str[INET_ADDRSTRLEN];
- ptr = inet_ntop(AF_INET, &foo.sin_addr, str, sizeof(str));
- 代替代碼
- ptr = inet_ntoa(foo.sin_addr);
下面給出隻支援IPv4的inet_pton函數的簡單定義和隻支援IPv4的inet_ntop函數的簡化版本。
- int inet_pton(int family, const char *strptr, void *addrptr)
- {
- if(family == AF_INET) {
- struct in_addr in_val;
- if (inet_aton(strptr, &in_val)) {
- memcpy(addrptr, &in_val, sizeof(struct in_addr));
- return ( );
- }
- }
- errno = EAFNOSUPPORT;
- return ( );
- }
- const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t lne)
- {
- const u_char *p = ( const u_char *) addrptr;
- if(family == AF_INET) {
- char temp[INET_ADDRSTRLEN];
- snprintf(temp, sizeof(temp), "%d.%d.%d.%d", p[ ], p[ ], p[ ], p[ ]);
- if ( strlen(temp) >= len){
- errno = ENOSPC;
- return ( NULL);
- }
- strcpy(strptr, temp);
- return (strptr);
- }
- errno = EAFNOSUPPORT;
- return ( NULL);
- }