1. 程式人生 > >inet_pton函式和inet_ntop函式的用法及簡單實現

inet_pton函式和inet_ntop函式的用法及簡單實現

        這兩個函式是隨IPv6出現的新函式,對於IPv4地址和IPv6地址都適用。函式名中的p和n非別代表表達(presentation)和數值(numeric)。地址的表達格式通常是ASCII字串,數值格式則是存放到套接字地址結構中的二進位制值。函式如下:

#include<arpa/inet.h>
int inet_pton(int family, const char *strptr, void *addrptr);
                                    返回:若成功則為1,若輸入不是有效的表達格式則為0,若出錯則為-1
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 (0);
        }
    }
    errno = EAFNOSUPPORT;
    return (-1);
}
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[0], p[1], p[2], p[3]);
        if (strlen(temp) >= len){
            errno = ENOSPC;
            return (NULL);
        }
        strcpy(strptr, temp);
        return (strptr);
    }
    errno = EAFNOSUPPORT;
    return (NULL);
}