当前位置: 首页 > news >正文

C++ 检测 IPv4 和 IPv6 地址合法性

C++ 检测 IPv4 和 IPv6 地址合法性

概述

在网络编程中,经常需要验证 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) {// 每个部分不能为空且长度不能超过3if (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;  // 跳过压缩段// 每个段长度不能超过4if (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 地址格式,且实现简单可靠。在必须使用手动解析的场景下,应进行充分的测试,覆盖各种边缘情况。

http://www.dtcms.com/a/325746.html

相关文章:

  • 朝花夕拾(一)-------布尔掩码(Boolean Mask)是什么?
  • npm install报错~[master] npm install npm error code ERESOLVE npm err
  • Redis 数据倾斜
  • 触想定制化工业一体机化身渔业预警终端,守望渔船安全
  • 验证二叉搜索树
  • (Arxiv-2025)Phantom:通过跨模态对齐实现主体一致性视频生成
  • 如何安装 Git (windows/mac/linux)
  • CodeBuddy IDE完全食用手册:从安装到生产力爆发的技术流解剖
  • 训推一体 | 暴雨X8848 G6服务器 x Intel®Gaudi® 2E AI加速卡
  • Android Audio实战——获取活跃音频类型(十五)
  • 2025 年国内可用 Docker 镜像加速器地址
  • 【深度学习3】向量化(Vectorization)
  • SpringUI Axure元件库:重塑高效原型设计的专业工具集
  • Agent在供应链管理中的应用:库存优化与需求预测
  • 从ELF到进程间通信:剖析Linux程序的加载与交互机制
  • QT之键盘控制虚拟遥控系统开发总结
  • Qt串口通信中继电器状态解析的优化实践
  • 跨平台、低延迟、可嵌入:实时音视频技术在 AI 控制系统中的进化之路
  • c++ 常见关键字
  • 带简易后台管理的米表系统 域名出售系统 自适应页面
  • 适用于高质量核磁共振(NMR)的溶剂推荐
  • 未来物联网大模型:物联网硬件+底层驱动+AI 自动生成和调优LUA脚本,
  • Maven 的 module 管理
  • 变频器实习总结13 传统数据存储、OSS和云数据库 RDS
  • 【11-计算机视觉介绍】
  • C#/.NET/.NET Core技术前沿周刊 | 第 49 期(2025年8.1-8.10)
  • 常用设计模式系列(十九)- 状态模式
  • Flink TableAPI 按分钟统计数据量
  • 电路笔记参考图
  • 老式大头显示器(CRT)和当前最高分辨率的LED显示器对比