实现ipv4和ipv6转换

#include#include#ifdef_WIN32#define_WINSOCK_DEPRECATED_NO_WARNINGS#include<WS2tcpip.h>#else#include<arpa/inet.h>#endifintinet4_pton(constchar*cp,uint32_t&ap){uint32_tacc=0;uint32_tdots=0;uint32_taddr=0;uin

大家好,又见面了,我是你们的朋友全栈君。

#include
#include
#ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WS2tcpip.h>
#else
#include <arpa/inet.h>
#endif

int inet4_pton(const char* cp, uint32_t& ap) {

uint32_t acc = 0;
uint32_t dots = 0;
uint32_t addr = 0;
uint32_t index = 0;

do {
    char cc = *cp;
    if (cc >= '0' && cc <= '9') {
        acc = acc * 10 + (cc - '0');
    }
    else if (cc == '.' || cc == '\0') {
        if (++dots > 3 && cc == '.') {
            return 0;
        }
        /* Fall through */

        if (acc > 255) {
            return 0;
        }

        addr += (acc << (index * 8));//各平台统一
        //从左往右,低位放
        //addr = addr << 8 | acc; // 这句是精华,每次将当前值左移八位加上后面的值
        ++index;
        acc = 0;
    }
} while (*cp++);

// Normalize the address 
if (dots < 3) {
    addr <<= 8 * (3 - dots);
}

ap = addr;
return 1;

}

void inet4_ntop(uint32_t value, std::string& str)
{

in_addr addr;
addr.s_addr = value;
str = inet_ntoa(addr);
}

int inet6_pton(const char* src, std::uint8_t* dst) {

if (src == nullptr) {

return 0;
}

constexpr  char  xdigits_l[] = "0123456789abcdef";
constexpr  char  xdigits_u[] = "0123456789ABCDEF";
const      char* xdigits = nullptr;
const      char* curtok = nullptr;
constexpr  int  NS_IN6ADDRSZ = 16;
constexpr   int NS_INT16SZ = 2;
std::uint8_t tmp[NS_IN6ADDRSZ] = { 0 };
std::uint8_t* tp = tmp;
std::uint8_t* endp = nullptr;
std::uint8_t* colonp = nullptr;
endp = tp + NS_IN6ADDRSZ;

/* Leading :: requires some special handling. */
if (*src == ':') {
    if (*++src != ':') {
        return 0;
    }
}

int              seen_xdigits = 0;
std::size_t    val = 0;
char  ch = 0;
while ((ch = *src++) != '\0') {
    const char* pch = nullptr;

    if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) {
        pch = strchr((xdigits = xdigits_u), ch);
    }

    if (pch != NULL) {
        val <<= 4;
        val |= (pch - xdigits);
        if (++seen_xdigits > 4) {
            return 0;
        }

        continue;
    }

    if (ch == ':') {
        curtok = src;
        if (!seen_xdigits) {
            if (colonp != nullptr) {
                return 0;
            }

            colonp = tp;
            continue;
        }
        else if (*src == 0) {
            return 0;
        }

        if (tp + NS_INT16SZ > endp) {
            return 0;
        }

        *tp++ = (u_char)(val >> 8) & 0xff;    //放在高位上
        *tp++ = (u_char)val & 0xff; //放在低位上
        seen_xdigits = 0;
        val = 0;
        continue;
    }

    if (ch == '.' && ((tp + 4) <= endp)) {
        uint32_t value = 0;
        if (inet4_pton(curtok, value)) {
            unsigned char* buf = (unsigned char*)&value;
            memcpy(tp, buf, 4);
            tp += 4;
            seen_xdigits = 0;
            break;  /*%< '\\' was seen by inet_pton4(). */
        }
    }

    return 0;
}

if (seen_xdigits) {
    if (tp + NS_INT16SZ > endp) {
        return 0;
    }

    *tp++ = (u_char)(val >> 8) & 0xff;
    *tp++ = (u_char)val & 0xff;
}

if (colonp != NULL) {
    if (tp == endp) {
        return 0;
    }

    const std::size_t n = tp - colonp;
    for (int i = 1; i <= n; i++) {
        endp[-i] = colonp[n - i];
        colonp[n - i] = 0;
    }

    tp = endp;
}

if (tp != endp) {
    return 0;
}

memcpy(dst, tmp, NS_IN6ADDRSZ);

return 1;

}

void inet6_ntop1(const u_char* src, std::string& dst) {

constexpr int NS_IN6ADDRSZ = 16;
constexpr int NS_INT16SZ = 2;
char tmp[100] = { 0 };
struct { int base, len; } best, cur;
std::size_t words[NS_IN6ADDRSZ / NS_INT16SZ] = { 0 };

memset(words, '\0', sizeof words);
for (int i = 0; i < NS_IN6ADDRSZ; i += 2) {
    words[i / 2] = (src[i] << 8) | src[i + 1];
}

best.base = -1;
cur.base = -1;
best.len = 0;
cur.len = 0;
for (int i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
    if (words[i] == 0) {
        if (cur.base == -1) {
            cur.base = i, cur.len = 1;
        }
        else {
            cur.len++;
        }
    }
    else {
        if (cur.base != -1) {
            if (best.base == -1 || cur.len > best.len) {
                best = cur;
            }

            cur.base = -1;
        }
    }
}
if (cur.base != -1) {
    if (best.base == -1 || cur.len > best.len) {
        best = cur;
    }
}
if (best.base != -1 && best.len < 2) {
    best.base = -1;
}

/*
 * Format the result.
 */
char* tp = tmp;
for (int i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
    /* Are we inside the best run of 0x00's? */
    if (best.base != -1 && i >= best.base &&
        i < (best.base + best.len)) {
        if (i == best.base) {
            *tp++ = ':';
        }

        continue;
    }
    /* Are we following an initial run of 0x00s or any real hex? */
    if (i != 0) {
        *tp++ = ':';
    }

    /* Is this address an encapsulated IPv4? */
    if (i == 6 && best.base == 0 &&
        (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
        std::string temp;
        temp.resize(20);
        memcpy(&temp[0], (char*)src + 12, 4);

        uint32_t value = 0;
        uint32_t* ptr = (uint32_t*)temp.data();
        value = *ptr;

        inet4_ntop(value, temp);
        std::size_t len = strlen(temp.c_str());
        memcpy(tp, temp.c_str(), len);
        tp += len;
        break;
    }

    std::stringstream sstream;
    sstream << std::hex << words[i];
    std::size_t len = strlen(sstream.str().c_str());
    memcpy(tp, sstream.str().c_str(), len);
    tp += len;
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) {
    *tp++ = ':';
}

*tp++ = '\0';

std::size_t len = strlen(tmp);
dst.resize(len);
memcpy(&dst[0], tmp, len);

}

int main()
{

/ipv4测试*/
std::string addr = “255.198.127.105”;
std::string addr100;
addr100.resize(20);
uint32_t value;
inet4_pton(addr.c_str(), value);
std::cout << value << std::endl;

inet4_ntop(value, addr100);
std::cout << addr100 << std::endl;

///*******ipv6测试*******/
//char* addr1 = _strdup("2000:0000:0000:0000:0001:2345:6789:abcd");
//struct in6_addr ip;
//struct in6_addr ip1;
//std::string str;
//std::string sss;
inet_pton(AF_INET6, addr1, &ip);
//inet6_pton(addr1, (uint8_t*)&ip.u);
//ip1.u = ip.u;
inet6_ntop1(ip.u.Byte, str);

//sss.resize(100);
//inet_ntop(AF_INET6, &ip1, &sss[0], INET6_ADDRSTRLEN);

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/126439.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • python模块有哪些_python typeerror

    python模块有哪些_python typeerrorpython将自己写的模块上传到PyPI服务器,报错error:<urlopenerror[SSL:CERTIFICATE_VERIFY_FAILED]certificatever

    2022年7月31日
    2
  • Ubuntu修改用户名和密码后无法登录_ubuntu默认用户名

    Ubuntu修改用户名和密码后无法登录_ubuntu默认用户名ubuntu修改用户名和密码项目场景:克隆别人的虚拟机后,想修改用户名和密码。问题描述:修改密码后,root和用户身份验证正常,但是继续修改用户名后,提示认证失败。原因分析:原因是修改用户名后,用户名和密码不匹配解决方案:若要修改用户名和密码,需要切换到root后修改。修改完成后需要确认用户身份验证是否通过,通过后才证明完成了修改,否则重启后会导致无法登陆。下面是修改用户名和密码的步骤。1.修改密码最好先修改密码,重启后再修改用户名。1)修改root密码:$sudopasswdr

    2022年9月29日
    0
  • 发送国外邮箱失败

    发送国外邮箱失败在公司当发送邮件给国外客户的时候,发送失败提示:点击下面链接:则代表地址被加入了黑名单,发送不到邮件。解决方法,点击方框内的网站,打开网页后拉到最下面:点击解除封禁跳转到则表示成功。需要1-2个小时进行解除! 转载于:https://blog.51cto.com/8763846/1629650…

    2022年7月12日
    23
  • 常见的计算机病毒种类有,五种常见的计算机病毒种类有哪些

    常见的计算机病毒种类有,五种常见的计算机病毒种类有哪些五种常见的计算机病毒种类有系统病毒、蠕虫病毒、木马病毒、脚本病毒、宏病毒。计算机病毒(ComputerVirus)是编制者在计算机程序中插入的破坏计算机功能或者数据的代码,能影响计算机使用,能自我复制的一组计算机指令或者程序代码。计算机病毒是人为制造的,有破坏性,又有传染性和潜伏性的,对计算机信息或系统起破坏作用的程序。它不是独立存在的,而是隐蔽在其他可执行的程序之中。计算机中病毒后,轻则影响机…

    2022年5月3日
    57
  • 机器人slam技术_激光二维扫描仪

    机器人slam技术_激光二维扫描仪机器人开发–二维激光SLAM介绍1SLAM简介1.1概述1.2应用1.3历史发展2SLAM中3个模块2.1前端里程计模块实现原理实现方法2.2后端优化模块2.3回环检测模块参考1SLAM简介1.1概述SLAM本质就是确定自己在哪里的哪里,如在苏州中心的正东边66米处。SLAM(SimultaneousLocalizationandMapping),也称为CML(ConcurrentMappingandLocalization),即时定位与地图构建,或并发

    2022年8月23日
    3
  • 电容类别及封装形式_电容的种类和应用范围

    电容类别及封装形式_电容的种类和应用范围按介质分为:陶瓷、云母、纸质、薄膜、电解电容电解电容一般铝电解电容和钽电容,单片机晶振旁边的是独石电容1法拉=103毫法=106微法=109纳法=1012皮法;1pf=10-3nf=10-6uf=10-9mf钽电容封装:电解电容插件封装…

    2022年8月22日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号