域名校验须严格遵循rfc 1034/1035分层验证:每个label长1–63字符、不含非法字符或首尾连字符、无连续“--”、无空label;全长≤253字符;用std::string_view手动切分并逐项校验最稳妥。

域名校验不能只靠正则,得按 RFC 1034/1035 拆解规则
直接用 std::regex 匹配一个“看起来像域名”的字符串(比如 ^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$)会漏掉大量合法域名,也放过不少非法输入。真实有效的域名判断必须分层验证:每个标签(label)长度、字符集、连字符位置、总长度、是否以点结尾等,都要单独检查。
核心约束来自 RFC:
- 每个 label 长度 1–63 字符
- 整个 FQDN(含点)≤ 253 字符
- label 只能含
a-z、0-9、-,且不能以-开头或结尾 - 不允许连续两个
- - 不能有空 label(即
..或开头/结尾为.)
用 std::string_view 分割 label 并逐个校验最稳妥
避免拷贝、不依赖第三方库,推荐用 std::string_view 手动切分。关键不是“能不能 split”,而是“split 后怎么验”——尤其要注意边界情况。
实操建议:
- 先 trim 两端空白(
std::isspace),空串直接返回 false - 检查首尾是否为
.:开头是.→ 无效;结尾是.→ 允许(表示 FQDN),但要去掉再处理 - 用
find_first_of('.')循环切出每个 label,每次检查:label.empty()、长度超 63、首/尾为'-'、含非法字符、连续"--" - 累计所有 label 长度 + 点数,确保 ≤ 253
示例片段(关键逻辑):
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
bool is_valid_label(std::string_view s) {
if (s.empty() || s.size() > 63) return false;
if (s[0] == '-' || s.back() == '-') return false;
for (size_t i = 0; i
<h3>别忽略国际化域名(IDN)和 Punycode 场景</h3>
<p>纯 ASCII 域名校验对 <code>中文.com</code> 或 <code>café.fr</code> 完全失效。如果业务需支持 IDN,必须先转 Punycode(如 <code>xn--fsq.xn--0zwm56d</code>),再走上述 ASCII 校验流程。</p>
<p>这意味着:</p>
- 不能跳过编码转换直接校验原始 Unicode 字符串
- C++ 标准库不提供 Punycode 实现,需引入
icu、libidn2或轻量级实现(如http://www.gnu.org/software/libidn/) - 若仅校验后端存储/日志中的域名(已标准化为 ASCII),可跳过这步;但前端传入或用户注册场景必须处理
getaddrinfo() 是运行时验证的兜底手段,但不能替代语法校验
即使字符串完全符合 RFC,也不代表域名真实存在或可解析。想确认是否“能用”,最终得调用 getaddrinfo() 并检查返回值:
- 传入
AI_NUMERICHOST会跳过 DNS 查询,只做语法检查(适合快速过滤明显非法输入) - 不带该 flag 时,它会真正发起 DNS 查询 —— 这有网络延迟、超时、DNSSEC 失败等副作用,不能用于高频校验
- 注意:它接受
localhost、[::1]等非标准格式,与纯域名定义不一致,需前置过滤
所以正确顺序是:语法校验(快、确定)→ 必要时 getaddrinfo()(慢、不确定)。
真正容易被忽略的是:label 内部的连字符限制(不能开头/结尾)、总长 253 的硬上限、以及 IDN 场景下 Punycode 转换的时机 —— 这三处出错,线上可能表现为偶发解析失败或安全绕过。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










