inet_pton的作用是将可读的IP地址(ipv4和ipv6均支持)字符串转换成网络序的函数

main.cpp

#include <Windows.h>
#include <iostream>

#include "my_net_pton.h"
using namespace std;

int main() {
    cout << "hello" << endl;

    int lRet = 0;
    UINT32 remote_address;
    lRet = my_pton(2, "192.168.6.38", &remote_address);
    cout << "remote_address:" << remote_address;
    lRet = my_pton(2, "193.168.6.38", &remote_address);
    cout << "remote_address:" << remote_address;

    return 0;
}

  my_net_pton.h

#ifndef MY_NET_PTON_H
#define MY_NET_PTON_H

#ifdef __cplusplus
extern "C" {
#endif
#define NS_INT16SZ   2
#define NS_INADDRSZ      4
#define NS_IN6ADDRSZ    16

	int my_pton(int af, const char* src, void* dst);

#ifdef __cplusplus
}
#endif

#endif

  my_net_pton.c

#include <ntdef.h>
#include <inaddr.h>
#include <in6addr.h>
#include "my_net_pton.h"
#include <common/my_wsa.h>

// ipv4是4个字节,xxx.yyy.mmm.nnn
// 注意:每个八位组第一个不能为0
// 每个八位组值不能大于255
// 只能有4个八位组
// 整个ip字符串中只能有数字和'.'符号
// dst的结构体不需要理会,只需要知道dst为接收内存且长度只能是4字节,其他随意
static int inet_pton4(const char *src, const char *end, unsigned char *dst)
{
    int saw_digit; // 每个八位组是否遇到数字标记,新的八位组将会清除标记
    int octets;     // 八位组的个数,ip地址合法,则为4个
    int ch;         // 遍历字符串,每次获得的字符
    // NS_INADDRSZ长度是4个字节, 宏定义在nameser.h中
    // 注意tmp不是字符串,仅仅是用来存放4个字节的数据,无'\0'
    unsigned char tmp[NS_INADDRSZ];
    unsigned char *tp;      // tp指的是八位组
    
    saw_digit = 0;
    octets = 0;
    *(tp = tmp) = 0; // *tp = 0;初始化必须为0,计算数值的时候会有依赖
    
    // 本函数实际上是转换成网络序的,所以方向是src -> end
    // 如果仅仅转换成二进制,方向是end -> src
    while (src < end)
    {
        ch = *src++; // 得到获得的ASCII值,src指向下一个字符
        if (ch >= '0' && ch <= '9')
        {
            // 八位组迭代,比如192.168.8.217
            // 以192为例:
            // 0 -> 0 * 10 + 1 = 1 -> 1 * 10 + 9 = 19 -> 19 * 10 + 2 = 192
            // 在将192赋值到tmp的第一个字节上(第一个八位组)
            unsigned int new = *tp * 10 + (ch - '0');
            
            // 八位组中不能以0开头,比如192.168.08.217是错误的
            if (saw_digit && *tp == 0)
                return 0;
            // 某一个八位组值不能超过255
            if (new > 255)
                return 0;
            
            // 八位组赋值
            *tp = (unsigned char)new;
            
            // 一般是在遇到'.'的时候,(! saw_digit)为0
            // 而在'.'之后的第一个数字置为1
            // 统计八位组的数目,由于在运行中,所以值不得超过4
            if (! saw_digit)
            {
                if (++octets > 4)
                    return 0;
                saw_digit = 1;
            }
        }
        else if (ch == '.' && saw_digit)
        {
            if (octets == 4)
                return 0;
            
            // 下一个八位组赋值,必须为0,方面迭代
            // saw_digit标记为未遇到数值
            *++tp = 0;
            saw_digit = 0;
        }
        else
            return 0; // 其他字符,直接返回错误
    }
    if (octets < 4)
        return 0;
    memcpy (dst, tmp, NS_INADDRSZ);
    return 1;
}
 
static int hex_digit_value(char ch)
{
    if ('0' <= ch && ch <= '9')
        return ch - '0';
    if ('a' <= ch && ch <= 'f')
        return ch - 'a' + 10;
    if ('A' <= ch && ch <= 'F')
        return ch - 'A' + 10;
    return -1;
}
 
static int inet_pton6(const char *src, const char *src_endp, unsigned char *dst)
{
    unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
    const char *curtok;
    int ch;
    size_t xdigits_seen;    /* Number of hex digits since colon.  */
    unsigned int val;
    
    tp = memset (tmp, '\0', NS_IN6ADDRSZ);
    endp = tp + NS_IN6ADDRSZ;
    colonp = NULL;
    
    /* Leading :: requires some special handling.  */
    if (src == src_endp)
        return 0;
    if (*src == ':')
    {
        ++src;
        if (src == src_endp || *src != ':')
            return 0;
    }
    
    curtok = src;
    xdigits_seen = 0;
    val = 0;
    while (src < src_endp)
    {
        ch = *src++;
        int digit = hex_digit_value ((char)ch);
        if (digit >= 0)
        {
            if (xdigits_seen == 4)
                return 0;
            val <<= 4;
            val |= digit;
            if (val > 0xffff)
                return 0;
            ++xdigits_seen;
            continue;
        }
        if (ch == ':')
        {
            curtok = src;
            if (xdigits_seen == 0)
            {
                if (colonp)
                    return 0;
                colonp = tp;
                continue;
            }
            else if (src == src_endp)
                return 0;
            if (tp + NS_INT16SZ > endp)
                return 0;
            *tp++ = (unsigned char) (val >> 8) & 0xff;
            *tp++ = (unsigned char) val & 0xff;
            xdigits_seen = 0;
            val = 0;
            continue;
        }
        if (ch == '.' && ((tp + NS_INADDRSZ) <= endp)
            && inet_pton4 (curtok, src_endp, tp) > 0)
        {
            tp += NS_INADDRSZ;
            xdigits_seen = 0;
            break;  /* '\0' was seen by inet_pton4.  */
        }
        return 0;
    }
    if (xdigits_seen > 0)
    {
        if (tp + NS_INT16SZ > endp)
            return 0;
        *tp++ = (unsigned char) (val >> 8) & 0xff;
        *tp++ = (unsigned char) val & 0xff;
    }
    if (colonp != NULL)
    {
        /* Replace :: with zeros.  */
        if (tp == endp)
        /* :: would expand to a zero-width field.  */
            return 0;
        size_t n = tp - colonp;
        memmove (endp - n, colonp, n);
        memset (colonp, 0, endp - n - colonp);
        tp = endp;
    }
    if (tp != endp)
        return 0;
    memcpy (dst, tmp, NS_IN6ADDRSZ);
    return 1;
}
 
static int _inet_pton_length(int af, const char *src, size_t srclen, void *dst)
{
    switch (af)
    {
        case AF_INET:
            return inet_pton4(src, src + srclen, dst);
        case AF_INET6:
            return inet_pton6(src, src + srclen, dst);
        default:
            //printf("invalid AF, af: %d.\n", af);
            return -1;
    }
    return -1;
}
 
int my_pton(int af, const char *src, void *dst)
{
    return _inet_pton_length(af, src, strlen(src), dst);
}
 
 
//void AddrConvertTest(void)
//{
//    char szIpv4[INET_ADDRSTRLEN] = "192.168.8.217";
//    //char szIpv4[INET_ADDRSTRLEN] = "192.168.10.1";
//    unsigned int ulIpv4 = 3232237785;
//    printf("ip: %s, dec: %u, little-endian-hex: %#x, big-endian-hex: %#x\n", szIpv4, ulIpv4, ulIpv4, htonl(ulIpv4));
//    
//    struct in_addr stIpv4Addr = {0};
//    int lRet = 0;
//    lRet = pton(AF_INET, szIpv4, &stIpv4Addr);
//    printf("pton ret: %d, ip: %s, s_addr: %#x.\n", lRet, szIpv4, stIpv4Addr.s_addr);
//    return;
//}
 
//void AddrConvertLibcTest(void)
//{
//    char szStrIp[] = "192.168.8.217";
//    unsigned int ulIp = 3232237785;
//    printf("ip: %s, dec: %u, little-endian-hex: %#x, big-endian-hex: %#x\n", szStrIp, ulIp, ulIp, htonl(ulIp));
//    char *pcTmp = NULL;
//    int lRet = 0;
//    struct in_addr stInAddr = {0};
//    stInAddr.s_addr = inet_addr("192.168.8.217");
//    pcTmp = inet_ntoa(stInAddr);
//    printf("inet_ntoa, ret: %s, s_addr: %#x.\n", pcTmp, stInAddr.s_addr);
//    
//    /** inet_addr 处理255.255.255.255以及错误的ip返回的结果为0xffffffff
//     */
//    stInAddr.s_addr = inet_addr("259.255.255.255");
//    printf("inet_addr s_addr: %#x.\n", stInAddr.s_addr);
//    
//    char szIp[INET_ADDRSTRLEN] = "192.168.8.217";
//    struct in_addr stOutAddr = {0};
//    lRet = inet_aton(szIp, &stOutAddr);
//    printf("inet_aton ret: %d, ip: %s, s_addr: %#x.\n", lRet, szIp, stOutAddr.s_addr);
//    
//    struct in_addr stAddr2 = {0};
//    char szIp2[INET_ADDRSTRLEN] = "192.168.8.217";
//    // 文本字符串格式转换成网络字节序的二进制地址
//    lRet = inet_pton(AF_INET, szIp2, &stAddr2);
//    int ipv4StructSize = sizeof(struct in_addr);
//    printf("inet_pton ret: %d, ip: %s, s_addr: %#x.\n", lRet, szIp2, stAddr2.s_addr);
//    
//    const char *pcTmp2 = NULL;
//    memset(szIp2, 0, sizeof(szIp2));
//    // 网络字节序的二进制地址转换成文本字符串格式
//    pcTmp2 = inet_ntop(AF_INET, &stAddr2, szIp2, INET_ADDRSTRLEN);
//    printf("inet_ntop ret: %s, ip: %s.\n", pcTmp2, szIp2);
//}