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地址内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Qt编写提示进度条的实现示例

    Qt编写提示进度条的实现示例

    进度条在很地方都可以使用到,Qt自带的进度条或者操作系统的进度条样式,不够炫,本文就介绍一下Qt编写自定义控件的提示进度条的实现示例,感兴趣的可以了解一下
    2021-12-12
  • C++11并发编程关于原子操作atomic的代码示例

    C++11并发编程关于原子操作atomic的代码示例

    今天小编就为大家分享一篇关于C++11并发编程关于原子操作atomic的代码示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • C++实现线性表顺序存储的示例代码

    C++实现线性表顺序存储的示例代码

    这篇文章主要为大家详细介绍了C++实现线性表顺序存储的相关知识,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的可以了解一下
    2023-03-03
  • 关于win32 gettimeofday替代方案

    关于win32 gettimeofday替代方案

    下面小编就为大家带来一篇关于win32 gettimeofday替代方案。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • 关于C语言中弱符号与弱引用的实际应用问题

    关于C语言中弱符号与弱引用的实际应用问题

    在编码过程中,我们经常遇到符号重定义的错误问题,本文通过实例代码展示给大家介绍了C语言弱符号与弱引用的实际应用问题,一起看看吧
    2021-09-09
  • string,CString,char*之间的转化

    string,CString,char*之间的转化

    下面是MFC/C++/C中字符类型CString, int, string, char*之间的转换的说明与举例,经常用的东西,相信对于用C/C++的朋友,还是比较有用的
    2013-03-03
  • C语言实现的统计素数并求和代码分享

    C语言实现的统计素数并求和代码分享

    这篇文章主要介绍了C语言实现的统计素数并求和代码分享,来自PAT平台(浙江大学计算机程序设计能力考试系统)的一个题目,需要的朋友可以参考下
    2014-08-08
  • C语言扫雷游戏的实现方法

    C语言扫雷游戏的实现方法

    这篇文章主要为大家详细介绍了C语言扫雷游戏的实现方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • C++之初识多态(Visual Studio 2019)的使用

    C++之初识多态(Visual Studio 2019)的使用

    文章主要解释了C++中的多态概念、实现细节及一些相关特性,如虚函数、override和final关键字、纯虚函数和抽象类,通过代码示例展示了多态原理,包括虚函数表和动态绑定的概念,并探讨了多继承下虚函数表的行为
    2026-04-04
  • C语言qsort函数使用方法详解

    C语言qsort函数使用方法详解

    qsort是一个库函数,基于快速排序算法实现的一个排序的函数,下面这篇文章主要给大家介绍了关于C语言qsort()函数使用的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-09-09

最新评论