Winsock2 中的 inet_ntoa() 已弃用?
inet_ntoa() in Winsock2 is deprecated?
我当时正在尝试使用 Winsock2,收到警告说 inet_ntoa()
已被弃用,我应该使用 inet_pton()
。我试过了,但它是小字节序的,所以保存在缓冲区中的整个字符串都是“错误的”。我猜 inet_ntoa()
是大端?
而且我只能将 inet_pton()
与 #include <ws2tcpip.h>
一起使用,所以对我来说,从这里开始变得更加混乱。为什么我应该使用 <winsock2.h>
库之外的其他东西?
目前,我通过使用 #pragma warning(disable : 4996)
来避免这种情况,我不喜欢这样做,因为我不想忽略所有警告。
整个 Winsock 主题对我来说就像一个迷宫,抱歉,如果我遗漏了一些信息,希望这些就够了。
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 version-agnostic 代码更容易一些。
如果您在使用 inet_ntop()
时遇到问题,那么您使用方法有误,但您没有显示您的代码。 IPv4 地址总是以“网络字节顺序”(大端)的二进制形式表示,即使在小端系统上,如 Windows.
至于 <ws2tcpip.h>
,那是 Winsock2 库的一部分。不需要 API 只有 1 个 header 文件(事实上,Win32 API 作为一个整体由 千 个 header文件,以 <windows.h>
).
开头但不限于
处理弃用警告的正确方法是更新您的代码以使用未弃用的现代 API,就像它希望您这样做的那样。否则,如果此时这不是您的选择,那么至少您可以只在受影响的代码上使用 #pragma warning(suppress : 4996)
,而不是全局使用 #pragma warning(disable : 4996)
。或者,您可以在项目设置中定义 _WINSOCK_DEPRECATED_NO_WARNINGS
,或者您可以在 #include
任何 Winsock2 header 之前在代码中 #define
它。
inet_ntoa()
有几个局限性限制了它在现代世界中的实用性。
一方面,它只适用于 IPv4 地址——如果您需要将 IPv6 地址转换为人类可读的文本,就 inet_ntoa()
而言,您就不太走运了。
另一个问题是 inet_ntoa()
returns 一个指向静态缓冲区的 char *
,这是有问题的——如果你不立即将字符串复制到其他地方,静态缓冲区的内容可能会在您读取之前被另一个 sockets-API 调用覆盖,这可能是一个难以追踪和修复的运行时错误。 (当多个线程大约同时调用 inet_ntoa()
时,也可能存在竞争条件,尽管微软 documentation page 的措辞让我怀疑微软可能正在返回一个指向线程本地缓冲区的指针以避免特定的蠕虫)
因此,最佳做法是尽可能避免调用 inet_ntoa()
,而是调用其现代替代方法 inet_ntop()。 (inet_ntop()
使用起来有点困难,但是避免了上面列出的问题)
我当时正在尝试使用 Winsock2,收到警告说 inet_ntoa()
已被弃用,我应该使用 inet_pton()
。我试过了,但它是小字节序的,所以保存在缓冲区中的整个字符串都是“错误的”。我猜 inet_ntoa()
是大端?
而且我只能将 inet_pton()
与 #include <ws2tcpip.h>
一起使用,所以对我来说,从这里开始变得更加混乱。为什么我应该使用 <winsock2.h>
库之外的其他东西?
目前,我通过使用 #pragma warning(disable : 4996)
来避免这种情况,我不喜欢这样做,因为我不想忽略所有警告。
整个 Winsock 主题对我来说就像一个迷宫,抱歉,如果我遗漏了一些信息,希望这些就够了。
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 version-agnostic 代码更容易一些。
如果您在使用 inet_ntop()
时遇到问题,那么您使用方法有误,但您没有显示您的代码。 IPv4 地址总是以“网络字节顺序”(大端)的二进制形式表示,即使在小端系统上,如 Windows.
至于 <ws2tcpip.h>
,那是 Winsock2 库的一部分。不需要 API 只有 1 个 header 文件(事实上,Win32 API 作为一个整体由 千 个 header文件,以 <windows.h>
).
处理弃用警告的正确方法是更新您的代码以使用未弃用的现代 API,就像它希望您这样做的那样。否则,如果此时这不是您的选择,那么至少您可以只在受影响的代码上使用 #pragma warning(suppress : 4996)
,而不是全局使用 #pragma warning(disable : 4996)
。或者,您可以在项目设置中定义 _WINSOCK_DEPRECATED_NO_WARNINGS
,或者您可以在 #include
任何 Winsock2 header 之前在代码中 #define
它。
inet_ntoa()
有几个局限性限制了它在现代世界中的实用性。
一方面,它只适用于 IPv4 地址——如果您需要将 IPv6 地址转换为人类可读的文本,就 inet_ntoa()
而言,您就不太走运了。
另一个问题是 inet_ntoa()
returns 一个指向静态缓冲区的 char *
,这是有问题的——如果你不立即将字符串复制到其他地方,静态缓冲区的内容可能会在您读取之前被另一个 sockets-API 调用覆盖,这可能是一个难以追踪和修复的运行时错误。 (当多个线程大约同时调用 inet_ntoa()
时,也可能存在竞争条件,尽管微软 documentation page 的措辞让我怀疑微软可能正在返回一个指向线程本地缓冲区的指针以避免特定的蠕虫)
因此,最佳做法是尽可能避免调用 inet_ntoa()
,而是调用其现代替代方法 inet_ntop()。 (inet_ntop()
使用起来有点困难,但是避免了上面列出的问题)