【问题标题】:inet_ntoa() in Winsock2 is deprecated?Winsock2 中的 inet_ntoa() 已弃用?
【发布时间】:2021-03-12 20:06:57
【问题描述】:

我当时正在尝试使用 Winsock2,并收到警告说 inet_ntoa() 已弃用,我应该使用 inet_pton()。我试过了,但它是小端的,所以保存在缓冲区中的整个字符串是“错误的”。我猜inet_ntoa() 是大端?

而且我只能将inet_pton()#include <ws2tcpip.h> 一起使用,所以对我来说,从这里开始变得更加混乱。为什么我应该使用<winsock2.h> 库之外的其他东西?

目前,我通过使用 #pragma warning(disable : 4996) 来避免这种情况,我不喜欢这种做法,因为我只是不想忽略所有警告。

整个 Winsock 主题对我来说就像一个迷宫,如果我遗漏了一些信息,请见谅,希望这就足够了。

【问题讨论】:

    标签: c++ winsock winsock2


    【解决方案1】:

    inet_pton() 不是inet_ntoa() 的继承者,而是inet_addr() 的继承者。你想要inet_ntop()

    inet_ntoa()/inet_ntop() 将 IP 地址从二进制形式转换为字符串形式。 inet_addr()/inet_pton()做相反的转换。

    但是,实际上有几个函数可以用来代替inet_ntoa(),包括getnameinfo()WSAAddressToString()RtlIpv4AddressToString()/RtlIpv6AddressToString()等。

    话虽如此,inet_ntoa() 确实已被弃用,因为它只支持 IPv4 地址。 inet_ntop()getnameinfo() 等函数同时支持 IPv4 和 IPv6 地址,这使得编写与 IP 版本无关的代码更容易一些。

    如果您在使用 inet_ntop() 时遇到问题,则说明您使用错误,但您没有显示您的代码。 IPv4 地址始终以“网络字节顺序”(大端)的二进制形式表示,即使在 Windows 等小端系统上也是如此。

    至于<ws2tcpip.h>,它是Winsock2 库的一部分。没有什么要求 API 只有 1 个头文件(实际上,整个 Win32 API 由 数千 个头文件组成,以 <windows.h> 开头但不限于)。

    处理弃用警告的正确方法是更新您的代码以使用未弃用的现代 API,就像它希望您那样。否则,如果此时您无法选择,那么至少您可以在受影响的代码上使用#pragma warning(suppress : 4996),而不是全局使用#pragma warning(disable : 4996)。或者,您可以在项目设置中定义 _WINSOCK_DEPRECATED_NO_WARNINGS,或者您可以在 #include'ing 任何 Winsock2 标头之前在代码中 #define 它。

    【讨论】:

    • 非常感谢您的解释!这就是我所需要的,我通过谷歌搜索找到了一些教程,更深入地研究了函数本身,但微软文档根本没有帮助。再次,非常感谢你为我节省了一天通过谷歌搜索的时间,哈哈。
    • 上次更新,出于某种原因,我认为docs.microsoft.com/en-us/windows/win32/api/ws2def/… 是 SOCKADDR_IN,但它在 SOCKADDR_IN 内部,它按预期工作,我只是向函数提供了错误信息。关闭...
    • @cpnuub 我想你指的是IN_ADDR,对吧?
    • 没错,这就是我发布链接的原因,你可以看到唯一的 IN_ADDR 变量是“sin_addr”
    【解决方案2】:

    inet_ntoa() 有一些限制,限制了它在现代世界中的用途。

    一方面,它仅适用于 IPv4 地址——如果您需要将 IPv6 地址转换为人类可读的文本,那么就inet_ntoa() 而言,您很不走运。

    另一个问题是inet_ntoa() 返回一个指向静态缓冲区的char *,这是有问题的——如果你不立即将字符串复制到其他地方,静态缓冲区的内容可能会被另一个覆盖在阅读之前调用 sockets-API,这可能是一个难以追踪和修复的运行时错误。 (当多个线程大约在同一时间调用inet_ntoa() 时,也可能存在竞争条件,尽管微软documentation page 的措辞让我怀疑微软可能会返回一个指向线程本地缓冲区的指针以避免这种特殊情况一罐蠕虫)

    因此,最佳做法是尽可能避免调用inet_ntoa(),而是调用其现代替代品inet_ntop()。 (inet_ntop() 使用起来有点困难,但它避免了上面列出的问题)

    【讨论】:

    • 是的,inet_ntoa() 使用线程本地缓冲区,因此在多个线程中并发调用是安全的。但你是对的,应该使用采用用户提供的缓冲区的更现代的函数之一。
    猜你喜欢
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 2022-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    相关资源
    最近更新 更多