C++检测IPv4和IPv6地址合法性的两种方法

 更新时间:2026年01月30日 10:04:59   作者:bkspiderx  
本文介绍了两种在C++中验证IPv4和IPv6地址合法性的方法,推荐使用系统原生接口inet_pton函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

概述

在网络编程中,经常需要验证 IP 地址的合法性。本文介绍两种在 C++ 中检测 IPv4 和 IPv6 地址合法性的方法:使用系统原生接口和手动解析验证。系统接口方法简单可靠,推荐优先使用;手动解析方法适用于无法使用系统接口的特殊场景。

方法一:使用系统原生接口(推荐)

利用 POSIX 标准中的 inet_pton 函数,该函数可同时支持 IPv4 和 IPv6 地址的验证,能正确处理各种合法格式(包括 IPv6 的压缩格式)。

#include <iostream>
#include <string>
#include <arpa/inet.h>  // 包含inet_pton函数

// 检测IPv4地址合法性
bool is_valid_ipv4(const std::string& ip) {
    struct in_addr addr;
    // inet_pton返回1表示成功,0表示格式错误,-1表示地址族错误
    return inet_pton(AF_INET, ip.c_str(), &addr) == 1;
}

// 检测IPv6地址合法性
bool is_valid_ipv6(const std::string& ip) {
    struct in6_addr addr;
    return inet_pton(AF_INET6, ip.c_str(), &addr) == 1;
}

// 检测是否为合法IP(IPv4或IPv6)
bool is_valid_ip(const std::string& ip) {
    return is_valid_ipv4(ip) || is_valid_ipv6(ip);
}

int main() {
    // 测试用例
    std::string ipv4_test1 = "192.168.1.1";
    std::string ipv4_test2 = "256.0.0.1";  // 非法(256超过255)
    std::string ipv6_test1 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
    std::string ipv6_test2 = "2001:db8:85a3::8a2e:370:7334";  // 压缩格式
    std::string ipv6_test3 = "2001:db8:85a3:::8a2e:370:7334"; // 非法(双冒号过多)

    std::cout << ipv4_test1 << " 是" << (is_valid_ipv4(ipv4_test1) ? "" : "非") << "合法IPv4\n";
    std::cout << ipv4_test2 << " 是" << (is_valid_ipv4(ipv4_test2) ? "" : "非") << "合法IPv4\n";
    std::cout << ipv6_test1 << " 是" << (is_valid_ipv6(ipv6_test1) ? "" : "非") << "合法IPv6\n";
    std::cout << ipv6_test2 << " 是" << (is_valid_ipv6(ipv6_test2) ? "" : "非") << "合法IPv6\n";
    std::cout << ipv6_test3 << " 是" << (is_valid_ipv6(ipv6_test3) ? "" : "非") << "合法IPv6\n";

    return 0;
}

代码解析

  1. 核心函数

    • inet_pton:将点分十进制(IPv4)或冒号分隔(IPv6)的 IP 地址字符串转换为二进制格式
    • 函数返回值:1 表示转换成功(地址合法),0 表示格式错误,-1 表示地址族错误
  2. 函数说明

    • is_valid_ipv4:检测 IPv4 地址,使用 AF_INET 地址族
    • is_valid_ipv6:检测 IPv6 地址,使用 AF_INET6 地址族
    • is_valid_ip:检测是否为合法 IP 地址(IPv4 或 IPv6)
  3. 测试用例

    • 包含合法和非法的 IPv4 地址
    • 包含完整格式、压缩格式和非法格式的 IPv6 地址

编译与运行

  • Linux/macOS

    g++ ip_checker.cpp -o ip_checker && ./ip_checker
    
  • Windows(需要链接 Winsock 库):

    g++ ip_checker.cpp -o ip_checker -lws2_32 && ip_checker.exe
    

方法二:手动解析验证

当无法使用系统接口时,可以通过手动解析字符串来验证 IP 地址格式。这种方法需要自己处理各种格式规则,实现相对复杂。

IPv4 手动验证

#include <string>
#include <sstream>
#include <vector>
#include <cctype>

// 分割字符串
std::vector<std::string> split(const std::string& s, char delim) {
    std::vector<std::string> parts;
    std::string part;
    std::istringstream iss(s);
    while (std::getline(iss, part, delim)) {
        parts.push_back(part);
    }
    return parts;
}

// 手动检测IPv4(点分十进制)
bool is_valid_ipv4_manual(const std::string& ip) {
    auto parts = split(ip, '.');
    
    // 必须有4个部分
    if (parts.size() != 4) return false;

    for (const auto& part : parts) {
        // 每个部分不能为空且长度不能超过3
        if (part.empty() || part.size() > 3) return false;
        
        // 检查是否全为数字
        for (char c : part) {
            if (!std::isdigit(c)) return false;
        }
        
        // 检查范围是否在0-255之间
        int num = std::stoi(part);
        if (num < 0 || num > 255) return false;
        
        // 检查是否有前导零(如"01"是非法的,"0"是合法的)
        if (part.size() > 1 && part[0] == '0') return false;
    }
    
    return true;
}

IPv6 手动验证

// 手动检测IPv6(冒号分隔)
bool is_valid_ipv6_manual(const std::string& ip) {
    auto parts = split(ip, ':');
    
    // IPv6地址段数应在2-8之间
    if (parts.size() < 2 || parts.size() > 8) return false;
    
    // 检查压缩符"::"是否出现且仅出现一次
    int double_colon_count = 0;
    for (const auto& part : parts) {
        if (part.empty()) {
            double_colon_count++;
        }
    }
    if (double_colon_count > 1) return false;
    
    // 检查每个段是否为合法的十六进制值
    for (const auto& part : parts) {
        if (part.empty()) continue;  // 跳过压缩段
        
        // 每个段长度不能超过4
        if (part.size() > 4) return false;
        
        // 检查是否为十六进制字符
        for (char c : part) {
            if (!std::isxdigit(c)) return false;
        }
    }
    
    return true;
}

手动解析注意事项

  1. IPv4 验证要点

    • 必须由 4 个部分组成,用点号分隔
    • 每个部分为 0-255 之间的整数
    • 不能有前导零(除非该部分就是 0)
  2. IPv6 验证要点

    • 必须由 2-8 个部分组成,用冒号分隔
    • 每个部分为 0-FFFF 之间的十六进制数
    • 支持压缩格式(::),但只能出现一次
    • 不处理特殊地址(如本地回环地址 ::1)的特殊验证
  3. 局限性

    • 手动解析容易遗漏边缘情况
    • 不支持所有合法格式(如 IPv6 的内嵌 IPv4 地址)
    • 实现复杂,维护成本高

总结

方法优点缺点适用场景
系统接口(inet_pton)简单可靠、支持所有合法格式、维护成本低依赖系统接口大多数常规场景
手动解析不依赖系统接口实现复杂、易出错、不支持所有格式无法使用系统接口的特殊场景

推荐优先使用系统接口方法,它能正确处理各种复杂的 IP 地址格式,且实现简单可靠。在必须使用手动解析的场景下,应进行充分的测试,覆盖各种边缘情况。

到此这篇关于C++检测IPv4和IPv6地址合法性的文章就介绍到这了,更多相关C++检测IPv4和IPv6地址内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 适合初学者的C语言转义字符讲解

    适合初学者的C语言转义字符讲解

    转义字符是很多程序语言、数据格式和通信协议的形式文法的一部分。对于一个给定的字母表,一个转义字符的目的是开始一个字符序列,使得转义字符开头的该字符序列具有不同于该字符序列单独出现(没有转义字符开头)时的语义。因此转义字符开头的字符序列被叫做转义序列
    2022-04-04
  • Windows安装配置C/C++(VS2017)OpenSSL开发环境配置教程

    Windows安装配置C/C++(VS2017)OpenSSL开发环境配置教程

    这篇文章主要为大家详细介绍了Windows安装配置C/C++,OpenSSL开发环境配置教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • C++实现MyString的示例代码

    C++实现MyString的示例代码

    本文主要介绍了C++实现MyString的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • Windows进程崩溃问题的定位方法

    Windows进程崩溃问题的定位方法

    这篇文章主要介绍了Windows进程崩溃问题的定位方法,本文使用nstd工具进行进程崩溃时内存和堆栈转储的方法查明问题所在,需要的朋友可以参考下
    2015-04-04
  • Qt实现简单TCP服务器

    Qt实现简单TCP服务器

    这篇文章主要为大家详细介绍了Qt实现简单TCP服务器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • 用C语言实现自动售货机

    用C语言实现自动售货机

    这篇文章主要为大家详细介绍了用C语言实现自动售货机,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C/C++经典算法之约瑟夫问题详解

    C/C++经典算法之约瑟夫问题详解

    这篇文章主要给大家介绍了关于C/C++经典算法之约瑟夫问题的相关资料,约瑟夫环问题是一道经典的数据结构的题目,本文介绍了解决约瑟夫问题的三种方法,需要的朋友可以参考下
    2021-07-07
  • 总结C/C++面试中可能会碰到的字符串指针题

    总结C/C++面试中可能会碰到的字符串指针题

    C/C++是最能体现程序员能力的语言之一,其功能强大,在IT行业的各个方面都有大量的应用。下面这篇文章主要介绍了总结了在C/C++面试中可能会碰到的字符串指针题,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-01-01
  • C语言实现航班订票系统

    C语言实现航班订票系统

    这篇文章主要为大家详细介绍了C语言实现航班订票系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • DEV C++源码编译后控制台输出中文乱码问题解决

    DEV C++源码编译后控制台输出中文乱码问题解决

    本文主要介绍了DEV C++源码编译后控制台输出中文乱码问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01

最新评论