'inet_addr': Use inet_pton() or InetPton() instead

举报
福州司马懿 发表于 2025/07/17 11:38:33 2025/07/17
【摘要】 这个警告是因为 inet_addr() 是旧版 WinSock API,已被标记为废弃(deprecated),微软推荐使用更安全的 InetPton()(Windows)或跨平台的 inet_pton()(POSIX)替代。以下是解决方案: 方法 1:使用 InetPton()(推荐,Windows 专用)InetPton() 是 inet_addr() 的现代替代品,支持 IPv4 和 ...

这个警告是因为 inet_addr() 是旧版 WinSock API,已被标记为废弃(deprecated),微软推荐使用更安全的 InetPton()(Windows)或跨平台的 inet_pton()(POSIX)替代。以下是解决方案:


方法 1:使用 InetPton()(推荐,Windows 专用)

InetPton()inet_addr() 的现代替代品,支持 IPv4 和 IPv6,且能检测无效 IP 格式。

示例代码

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h> // 需要包含此头文件
#pragma comment(lib, "ws2_32.lib")

bool IsNetworkAvailable() {
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        return false;
    }

    SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET) {
        WSACleanup();
        return false;
    }

    // 设置超时(可选)
    DWORD timeout = 3000; // 3秒
    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout));
    setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout));

    // 使用 InetPton 替代 inet_addr
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(53);
    if (InetPtonA(AF_INET, "8.8.8.8", &addr.sin_addr) != 1) {
        closesocket(sock);
        WSACleanup();
        return false; // IP 格式无效
    }

    bool isConnected = (connect(sock, (sockaddr*)&addr, sizeof(addr)) == 0);
    closesocket(sock);
    WSACleanup();

    return isConnected;
}

int main() {
    if (IsNetworkAvailable()) {
        std::cout << "Network is available.\n";
    } else {
        std::cout << "Network may be down or restricted.\n";
    }
    return 0;
}

关键改进

  1. 更安全的 IP 解析InetPton() 能检测无效 IP(如 "256.1.1.1"),而 inet_addr() 会静默返回 INADDR_NONE
  2. 支持 IPv6:改用 AF_INET6InetPtonW()(宽字符版)即可支持 IPv6。

方法 2:使用 inet_pton()(跨平台,POSIX 标准)

如果代码需要跨平台(Linux/macOS/Windows),可以使用 inet_pton()(需定义 _WIN32_WINNT >= 0x0600 或包含 <ws2tcpip.h>)。

示例代码

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h> // 必须包含此头文件
#pragma comment(lib, "ws2_32.lib")

bool IsNetworkAvailable() {
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        return false;
    }

    SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET) {
        WSACleanup();
        return false;
    }

    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(53);

    // 使用 inet_pton(跨平台)
    if (inet_pton(AF_INET, "8.8.8.8", &addr.sin_addr) != 1) {
        closesocket(sock);
        WSACleanup();
        return false; // IP 格式无效
    }

    bool isConnected = (connect(sock, (sockaddr*)&addr, sizeof(addr)) == 0);
    closesocket(sock);
    WSACleanup();

    return isConnected;
}

方法 3:临时禁用警告(不推荐)

如果暂时不想修改代码,可以定义 _WINSOCK_DEPRECATED_NO_WARNINGS 来屏蔽警告:

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h>
// 其余代码不变...

缺点:只是隐藏警告,并未解决潜在的安全问题。


总结

方法 适用场景 优点 缺点
InetPton() Windows 专用 安全、支持 IPv4/IPv6 仅限 Windows
inet_pton() 跨平台 标准 POSIX,兼容 Linux/macOS 需确保头文件正确
禁用警告 临时兼容旧代码 快速解决编译警告 不推荐长期使用

最佳实践

  • Windows 优先用 InetPton()(更现代)。
  • 跨平台代码用 inet_pton()(需检查平台兼容性)。
  • 避免 inet_addr(),因为它无法处理 IPv6 且不检查无效 IP。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。