gpt4 book ai didi

IPv6 的 Swift getnameinfo 不可靠的结果

转载 作者:可可西里 更新时间:2023-11-01 02:04:15 29 4
gpt4 key购买 nike

我在 sockaddr 上有以下扩展:

extension sockaddr {
/// Indicates if this is an IPv4 address.
var isIPv4: Bool {
return sa_family == UInt8(AF_INET)
}

/// Indicates if this is an IPv6 address.
var isIPv6: Bool {
return sa_family == UInt8(AF_INET6)
}

/// Returns the address in string notation.
var address: String? {
var result: String = ""
var me = self
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))

if getnameinfo(&me, socklen_t(me.sa_len), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST) == 0 {
result = String(cString: hostname)
}

return result
}
}

在我的代码的另一部分,我调用 getifaddrs 来获取当前设备的接口(interface)地址。上面的代码在 IPv4 上运行良好,但在 IPv6 上有些不可靠。

我得到的结果如下:192.168.1.10fe80::e0fa:1204:100:0

当我将行 var result: String = "" 更改为 var result: String? = 无。 IPv6地址突然变成了fe80::,其余的都被截断了。

更奇怪的是,当我像这样切换 var resultvar me = self 行时:

extension sockaddr {
/// Indicates if this is an IPv4 address.
var isIPv4: Bool {
return sa_family == UInt8(AF_INET)
}

/// Indicates if this is an IPv6 address.
var isIPv6: Bool {
return sa_family == UInt8(AF_INET6)
}

/// Returns the address in string notation.
var address: String? {
var me = self
var result: String = ""
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))

if getnameinfo(&me, socklen_t(me.sa_len), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST) == 0 {
result = String(cString: hostname)
}

return result
}
}

那么该函数将只对 IPv4 地址有效。 getnameinfo 将返回 4 (FAIL)。

这是在调试期间,据我所知没有任何优化。不管我是在模拟器上还是在真实设备上运行它都没有关系。

有人可以解释为什么会这样吗?

最佳答案

问题是 getnameinfo 需要一个可以是 sockaddr_insockaddr_in6 的指针。该函数的定义有点困惑,因为它需要一个 sockaddr 指针。

因为我正在使用扩展来提取 IP 地址,所以正在制作内存内容的副本。这对 IPv4 来说不是问题,因为 sockaddr_in 的大小与 sockaddr 的大小相同。但是对于 IPv6,sockaddr_in6sockaddr 结构体大,一些相关信息被截断。

我的命令顺序可能决定了在 sockaddr 地址之后直接存储在内存中的内容。有时它看起来像是一个正确的 IPv6 地址,但实际上是错误的。

我通过将我的扩展程序移动到网络接口(interface) ifaddrs 解决了这个问题:

extension ifaddrs {
/// Returns the IP address.
var ipAddress: String? {
var buffer = [CChar](repeating: 0, count: Int(NI_MAXHOST))
let address = ifa_addr.pointee
let result = getnameinfo(ifa_addr, socklen_t(address.sa_len), &buffer, socklen_t(buffer.count), nil, socklen_t(0), NI_NUMERICHOST)
return result == 0 ? String(cString: buffer) : nil
}
}

感谢@MartinR 找到问题的原因!

关于IPv6 的 Swift getnameinfo 不可靠的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44478074/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com